<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/%E6%AD%A6%E6%B1%8932x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/%E6%AD%A6%E6%B1%8916x16.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib1/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib1/pace/pace-theme-center-simple.min.css">
  <script src="/lib1/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"example.com","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta property="og:type" content="website">
<meta property="og:title" content="Technological Blog">
<meta property="og:url" content="http://example.com/page/9/index.html">
<meta property="og:site_name" content="Technological Blog">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="Li Yudong">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://example.com/page/9/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>Technological Blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Technological Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">IT小白的成长之旅</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="tags fa-fw"></i>标签<span class="badge">18</span></a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="th fa-fw"></i>分类<span class="badge">14</span></a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="archive fa-fw"></i>归档<span class="badge">95</span></a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/tiarmor1" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/09/06/%E5%AD%A6%E6%A0%A1%E9%A1%B9%E7%9B%AE%E5%BA%94%E7%94%A8/%E6%B7%B1%E5%85%A5%E6%8E%A2%E7%A9%B6JavaScript/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/09/06/%E5%AD%A6%E6%A0%A1%E9%A1%B9%E7%9B%AE%E5%BA%94%E7%94%A8/%E6%B7%B1%E5%85%A5%E6%8E%A2%E7%A9%B6JavaScript/" class="post-title-link" itemprop="url">深入探究JavaScript</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-09-06 21:28:16" itemprop="dateCreated datePublished" datetime="2020-09-06T21:28:16+08:00">2020-09-06</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:32:20" itemprop="dateModified" datetime="2021-11-03T16:32:20+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93/" itemprop="url" rel="index"><span itemprop="name">面试总结</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <h1 id="JS方法-函数重载的姿势"><a href="#JS方法-函数重载的姿势" class="headerlink" title="JS方法/函数重载的姿势"></a>JS方法/函数重载的姿势</h1><p>JavaScript不支持重载的语法，它没有重载所需要的函数签名。</p>
<blockquote>
<p>ECMAScript函数不能像传统意义上那样实现重载。而在其他语言（如 Java）中，可以为一个函数编写两个定义，只要这两个定义的签名（接受的参数的类型和数量）不同即可。如前所述，<strong>ECMAScirpt函数没有签名</strong>，因为其参数是由包含零或多个值的数组来表示的。而<strong>没有函数签名，真正的重载是不可能做到的</strong>。 — <em>JavaScript高级程序设计（第3版）3.7.2小节</em></p>
</blockquote>
<p>在JavaScript中，函数名本身就是变量，函数声明类似于变量赋值。当同个函数名被多次声明时，后声明的内容将覆盖前面的内容。尽管JavaScript无法做到真正的重载，但是可以通过检查传入函数中参数的类型和数量并作相应的处理，从而实现重载的效果，曲线救国。</p>
<h2 id="借助流程控制语句"><a href="#借助流程控制语句" class="headerlink" title="借助流程控制语句"></a>借助流程控制语句</h2><p>通过判断传入参数的数量（arguments.length），执行相应的代码块。</p>
<h2 id="巧用闭包特性"><a href="#巧用闭包特性" class="headerlink" title="巧用闭包特性"></a>巧用闭包特性</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> ninja = &#123;&#125;;</span><br><span class="line">addMethod(ninja, <span class="string">'whatever'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;<span class="comment">/* code */</span>&#125;);</span><br><span class="line">addMethod(ninja, <span class="string">'whatever'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">a</span>)</span>&#123;<span class="comment">/* code */</span>&#125;);</span><br><span class="line">addMethod(ninja, <span class="string">'whatever'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">a,b</span>)</span>&#123;<span class="comment">/* code */</span>&#125;);</span><br></pre></td></tr></table></figure>

<p>addMethod函数接收3个参数：目标对象、目标方法名、函数体，当函数被调用时：</p>
<p>先将目标object[name]的值存入变量old中，因此<strong>起初old中的值可能不是一个函数</strong>；接着向object[name]赋值一个代理函数，并且由于变量old、fn在代理函数中被引用，所以<strong>old、fn将常驻内存</strong>不被回收。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">addMethod</span>(<span class="params">object, name, fn</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> old = object[name];  <span class="comment">// 保存前一个值，以便后续调用</span></span><br><span class="line">  object[name] = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;  <span class="comment">// 向object[name]赋值一个代理函数</span></span><br><span class="line">    <span class="comment">// 判断fn期望接收的参数与传入参数个数是否一致</span></span><br><span class="line">    <span class="keyword">if</span> (fn.length == <span class="built_in">arguments</span>.length)</span><br><span class="line">      <span class="comment">// 若是，则调用fn</span></span><br><span class="line">      <span class="keyword">return</span> fn.apply(<span class="keyword">this</span>, <span class="built_in">arguments</span>)</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> old == <span class="string">'function'</span>)  <span class="comment">// 若否，则判断old的值是否为函数</span></span><br><span class="line">      <span class="comment">// 若是，则调用old</span></span><br><span class="line">      <span class="keyword">return</span> old.apply(<span class="keyword">this</span>, <span class="built_in">arguments</span>);</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>代理函数被调用时：</p>
<p>先判断传入参数与<strong>其父级作用域中fn</strong>期望接收参数的个数是否一致，若是则调用该fn；</p>
<p>若否，则判断<strong>其父级作用域中old</strong>值类型是否为函数，若是则调用该old；</p>
<p> 当old中存有上一次生成的代理函数时，则会重复前面两个步骤，直至old值<strong>不为代理函数</strong>。</p>
<hr>
<p>上述两种方法都是通过检查参数个数来实现重载，<strong>不区分参数类型</strong>。此外，方法1在继承时重载的那些函数无法被重写，而方法2通过逐个执行代理函数，比对参数个数，直至找到目标函数，效率不高。</p>
<h2 id="巧用引用类型特性"><a href="#巧用引用类型特性" class="headerlink" title="巧用引用类型特性"></a>巧用引用类型特性</h2><p><strong>核心思想</strong>：由于ECMAScript函数是一种<strong>引用类型</strong>对象，可扩展属性与方法。借此通过创建一个容器用于存储要重载的函数，并将容器挂载到代理函数上以便后续访问，而代理函数利用闭包特性访问容器。</p>
<p><strong>重载顺序</strong>：首先查找参数类型匹配的函数，其次查找参数个数匹配的函数。</p>
<p><strong>存储格式</strong>：键值对，键名由逗号与参数个数或参数类型组成，键值为要重载的函数，如下：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">',0'</span>: <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;<span class="comment">/* code */</span>&#125;,</span><br><span class="line">  <span class="string">',1'</span>: <span class="function"><span class="keyword">function</span>(<span class="params">a</span>)</span>&#123;<span class="comment">/* code */</span>&#125;,</span><br><span class="line">  <span class="string">',string,number'</span>: <span class="function"><span class="keyword">function</span>(<span class="params">a,b</span>)</span>&#123;<span class="comment">/* code */</span>&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>工具函数被调用时</strong>：</p>
<ol>
<li>先判断是否已重载过，若有，直接将要重载的函数按格式存入容器；</li>
<li>若未重载过，则创建一个容器变量；</li>
<li> 判断未重载前的值是否为一个函数，若是，则以逗号+参数个数的格式存入容器；</li>
<li>将要重载的函数存入容器；</li>
<li>代理原函数，并将容器挂载到代理函数上；</li>
<li>当代理函数被调用时，将依次查找容器中匹配的函数并调用。</li>
</ol>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 重载工具函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">&#123;Object&#125;</span> <span class="variable">ctx</span></span> - 上下文</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">&#123;String&#125;</span> <span class="variable">name</span></span> - 函数名</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">&#123;Function&#125;</span> <span class="variable">fn</span></span> - 函数体</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">&#123;String&#125;</span> <span class="variable">type</span></span> - 参数类型</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author </span>范围兄 &lt;ambit_tsai<span class="doctag">@qq</span>.com&gt;</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@example </span>不指定参数类型</span></span><br><span class="line"><span class="comment"> *  overload(obj, 'do', function()&#123;...&#125;);</span></span><br><span class="line"><span class="comment"> *  overload(obj, 'do', function(a)&#123;...&#125;);</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@example </span>指定参数类型</span></span><br><span class="line"><span class="comment"> *  overload(obj, 'do', function(a,b)&#123;...&#125;, 'string,number');</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">overload</span>(<span class="params">ctx, name, fn, type</span>)</span>&#123;</span><br><span class="line">  type = type? type.trim().toLowerCase(): fn.length;</span><br><span class="line">  <span class="comment">// 已重载过</span></span><br><span class="line">  <span class="keyword">if</span>(<span class="keyword">typeof</span> ctx[name]===<span class="string">'function'</span> &amp;&amp; <span class="keyword">typeof</span> ctx[name]._$fnMap===<span class="string">'object'</span>)&#123;</span><br><span class="line">    ctx[name]._$fnMap[<span class="string">','</span>+type] = fn;	<span class="comment">// 将fn存入_$fnMap</span></span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 未重载过</span></span><br><span class="line">  <span class="keyword">var</span> fnMap = &#123;&#125;;   <span class="comment">// 容器</span></span><br><span class="line">  <span class="keyword">if</span>(<span class="keyword">typeof</span> ctx[name] === <span class="string">'function'</span>)&#123;</span><br><span class="line">    <span class="comment">// 若ctx[name]是一个函数，则存入容器</span></span><br><span class="line">    fnMap[<span class="string">','</span>+ctx[name].length] = ctx[name];</span><br><span class="line">  &#125;</span><br><span class="line">  fnMap[<span class="string">','</span>+type] = fn;</span><br><span class="line">  ctx[name] = <span class="function"><span class="keyword">function</span> <span class="title">overloading</span>(<span class="params"></span>)</span>&#123;   <span class="comment">// 代理</span></span><br><span class="line">    <span class="keyword">var</span> args = <span class="built_in">arguments</span>, </span><br><span class="line">        len = args.length, </span><br><span class="line">        type, i;</span><br><span class="line">    <span class="keyword">for</span>(i=<span class="number">0</span>, type=<span class="string">''</span>; i&lt;len; ++i)&#123;  <span class="comment">// 计算参数类型</span></span><br><span class="line">      type += <span class="string">','</span> + <span class="keyword">typeof</span> args[i];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 依次匹配：参数类型-&gt;参数个数</span></span><br><span class="line">    <span class="keyword">if</span>(fnMap[type]) <span class="keyword">return</span> fnMap[type].apply(<span class="keyword">this</span>, args);</span><br><span class="line">    <span class="keyword">if</span>(fnMap[<span class="string">','</span>+len]) <span class="keyword">return</span> fnMap[<span class="string">','</span>+len].apply(<span class="keyword">this</span>, args);</span><br><span class="line">    <span class="keyword">throw</span> <span class="string">'Overload: no matched function'</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">  ctx[name]._$fnMap = fnMap;   <span class="comment">// 将fnMap挂载到代理上</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="JS异步操作的方法"><a href="#JS异步操作的方法" class="headerlink" title="JS异步操作的方法"></a>JS异步操作的方法</h1><h2 id="回调函数"><a href="#回调函数" class="headerlink" title="回调函数"></a>回调函数</h2><p><strong>回调函数是异步编程中最基本的方法</strong>。假设有<strong>三个函数f1、f2、f3</strong>，<strong>f2需要等待f1</strong>的执行结果，<strong>而f3是独立的，不需要f1和f2的结果</strong>，如果我们写成同步，就是这样的：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">　　f1();</span><br><span class="line">　　f2();　　f3()</span><br></pre></td></tr></table></figure>

<p>如果f1执行的很快，可以； 但是如果f1执行的很慢，那么f2和f3就会被阻塞，无法执行。这样的效率是非常低的。但是<strong>我们可以改写，将f2写成是f1的回调函数，如下：</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">f1</span>(<span class="params">callback</span>)</span>&#123;</span><br><span class="line">　　　　setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">　　　　　　<span class="comment">// f1的任务代码</span></span><br><span class="line">　　　　　　callback();</span><br><span class="line">　　　　&#125;, <span class="number">1000</span>);</span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>　那么这时候执行代码就是这样：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">f1(f2);</span><br><span class="line">f3()</span><br></pre></td></tr></table></figure>

<p>这样，就是一个异步的执行了，即使f1很费时间，但是<strong>由于是异步的，那么f3()就会很快的得到执行，而不会受到f1和f2的影响。</strong></p>
<p><strong>注意： 如果我们把f1写成这样呢？</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f1</span>(<span class="params">callback</span>)</span>&#123;</span><br><span class="line">　　<span class="comment">// f1的任务代码</span></span><br><span class="line">　　callback();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>然后，我们同样可以这么调用：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">f1(f2);</span><br><span class="line">f3()</span><br></pre></td></tr></table></figure>

<p><strong>这时候还是异步的吗？</strong> <strong>答案：不是异步。</strong> 这里的回调函数并非真正的回调函数，如果没有利用setTimeout含函数，那么f3()的执行同样需要等到f1(f2)完全执行完毕，<strong>这里要注意</strong>。而我们就是利用setTImeout才能做出真正的回调函数。</p>
<h2 id="事件监听"><a href="#事件监听" class="headerlink" title="事件监听"></a>事件监听</h2><p>另一种异步的思路是采用事件驱动模式。任务的执行不取决于代码的顺序， 而取决于某个事件是否发生。 还是以f1、f2、f3为例子。 首先，<strong>为f1绑定一个事件</strong>（这里采用jquery的写法）：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">f1.on(<span class="string">'done'</span>, f2);</span><br><span class="line">f3()</span><br></pre></td></tr></table></figure>

<p>这里的意思是： 当f1发生了done事件，就执行f2， 然后，我们对f1进行改写：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">f1</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">　　　　setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">　　　　　　<span class="comment">// f1的任务代码</span></span><br><span class="line">　　　　　　f1.trigger(<span class="string">'done'</span>);</span><br><span class="line">　　　　&#125;, <span class="number">1000</span>);</span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>f1.trigger(‘done’)表示， 执行完成后，立即触发done事件，从而开始执行f2。</p>
<p><strong>这种方法的优点</strong>就是比较容易理解，可以绑定多个事件，每个事件可以指定多个回调函数，而且可以去耦合，有利于实现模块化<strong>，缺点就是整个程序都要变成事件驱动型，运行流程会变得很不清晰。</strong></p>
<h2 id="发布订阅"><a href="#发布订阅" class="headerlink" title="发布订阅"></a>发布订阅</h2><p>第二种方法的事件，实际上我们完全可以理解为“信号”，即f1完成之后，触发了一个 ‘done’，信号，然后再开始执行f2。</p>
<p><strong>我们假定，存在一个“信号中心”，某个任务执行完成，就向信号中心“发布”（publish）一个信号，其他任务可以向信号中心“订阅”这个信号， 从而知道什么时候自己可以开始执行。 这个就叫做“发布/订阅模式”， 又称为“观察者”模式 。</strong> </p>
<p>这个模式有多种实现， 下面采用Ben Alman的Tiny PUb/Sub，这是jQuery的一个插件。</p>
<p>首先，<strong>f2向”信号中心”jquery订阅”done”信号，</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jQuery.subscribe(<span class="string">"done"</span>, f2);</span><br></pre></td></tr></table></figure>

<p>然后，f1进行如下改写：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">f1</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">　　　　setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">　　　　　　<span class="comment">// f1的任务代码</span></span><br><span class="line">　　　　　　jQuery.publish(<span class="string">"done"</span>);</span><br><span class="line">　　　　&#125;, <span class="number">1000</span>);</span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p><strong>jquery.pushlish(“done”)的意思是： f1执行完成后，向“信号中心”jQuery发布“done”信号，从而引发f2的执行。</strong> </p>
<p>此外，f2完成执行后，也可以取消订阅（unsubscribe）。</p>
<p>　　</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　jQuery.unsubscribe(<span class="string">"done"</span>, f2);</span><br></pre></td></tr></table></figure>

<p>这种方法的性质和“事件监听”非常类似，但是明显是优于前者的，<strong>因为我们可以通过查看“消息中心”，了解到存在多少信号、每个信号有多少个订阅者，从而监控程序的运行。</strong></p>
<h2 id="promise对象"><a href="#promise对象" class="headerlink" title="promise对象"></a>promise对象</h2><p>promise是commonjs工作组提出来的一种规范，<strong>目的是为异步编程提供统一接口。</strong></p>
<p>简答的说，它的思想是每一个异步任务返回一个promise对象，该对象有一个then方法，允许指定回调函数。 比如,f1的回调函数f2，可以写成：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">f1().then(f2);</span><br></pre></td></tr></table></figure>

<p>f1要进行下面的改写（这里使用jQuery的实现）：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">　<span class="function"><span class="keyword">function</span> <span class="title">f1</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">　　　　<span class="keyword">var</span> dfd = $.Deferred();</span><br><span class="line">　　　　setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">　　　　　　<span class="comment">// f1的任务代码</span></span><br><span class="line">　　　　　　dfd.resolve();</span><br><span class="line">　　　　&#125;, <span class="number">500</span>);</span><br><span class="line">　　　　<span class="keyword">return</span> dfd.promise;</span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>这样的优点在于，<strong>回调函数编程了链式写法，程序的流程可以看得很清楚，而且有一整套的配套方法，可以实现很多强大的功能 。</strong></p>
<p>如：指定多个回调函数：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　f1().then(f2).then(f3);</span><br></pre></td></tr></table></figure>

<p>再比如，指定发生错误时的回调函数：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">f1().then(f2).fail(f3);</span><br></pre></td></tr></table></figure>

<p>而且，他还有一个前面三种方法都没有的好处：如果一个任务已经完成，再添加回调函数，该回调函数会立即执行。　所以，你不用担心是否错过了某个事件或者信号，<strong>这种方法的确定就是编写和理解，都比较困难。</strong></p>
<h2 id="generator函数的异步应用"><a href="#generator函数的异步应用" class="headerlink" title="generator函数的异步应用"></a>generator函数的异步应用</h2><p>而<strong>generator函数将JavaScript异步编程带入了一个全新的阶段！</strong></p>
<p>比如，有一个任务是读取文件进行处理，任务的第一段是向操作系统发出请求，要求读取文件。然后，<strong>程序执行其他任务</strong>，等到操作系统返回文件，再<strong>接着执行</strong>任务的第二段（处理文件）。<strong>这种不连续的执行，就叫做异步。</strong></p>
<p>相应地，连续的执行就叫做同步。由于是连续执行，不能插入其他任务，所以操作系统从硬盘读取文件的这段时间，程序只能干等着<strong>。</strong></p>
<p>　　  </p>
<p><strong>协程</strong></p>
<p>　传统的编程语言中，早就有了异步编程的解决方案，<strong>其中一种叫做协程</strong>，意思是多个线程互相协作，<strong>完成异步任务</strong>。</p>
<p>　　协程优点像函数，又有点像线程，运行流程如下：</p>
<ul>
<li>第一步，协程<code>A</code>开始执行。</li>
<li>第二步，协程<code>A</code>执行到一半，<strong>进入暂停</strong>，<strong>执行权转移</strong>到协程<code>B</code>。</li>
<li>第三步，（一段时间后）协程<code>B</code><strong>交还执行权</strong>。</li>
<li>第四步，协程<code>A</code><strong>恢复执行</strong>。</li>
</ul>
<p>　　<strong>上面的协程A，就是异步任务，因为它分为两段（或者多段）执行。</strong> </p>
<p>　　举例来说，读取文件的协程写法如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function *asyncJob() &#123;</span><br><span class="line">  &#x2F;&#x2F; ...其他代码</span><br><span class="line">  var f &#x3D; yield readFile(fileA);</span><br><span class="line">  &#x2F;&#x2F; ...其他代码</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>　　上面代码的函数asyncJob是一个协程，<strong>奥妙就在于yield命令，</strong> 它表示执行到此处，<strong>执行权交给其他协程</strong>，也就是说<strong>yield命令是异步两个阶段的分界线。</strong> </p>
<p>　　协程遇到yield命令就暂停，等到执行权返回，再从暂停的地方继续向后执行，它的最大优点就是<strong>代码的写法非常像同步操作</strong>，如果去除yield命令，简直是一模一样。</p>
<p><strong>协程的Generator函数实现</strong></p>
<p>　　Generator函数是协程在ES6中的实现，<strong>最大特点就是可以交出函数的执行权（即暂停执行）。</strong></p>
<p>　　整个<strong>Generator函数就是一个封装的异步任务</strong>，或者说异步任务的容器。 异步任务需要暂停的地方，都用yield语句注明。 如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">function* gen(x) &#123;</span><br><span class="line">  var y &#x3D; yield x + 2;</span><br><span class="line">  return y;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">var g &#x3D; gen(1);</span><br><span class="line">g.next() &#x2F;&#x2F; &#123; value: 3, done: false &#125;</span><br><span class="line">g.next() &#x2F;&#x2F; &#123; value: undefined, done: true &#125;</span><br></pre></td></tr></table></figure>

<p>　　在调用gen函数时 gen(1)， 会<strong>返回一个内部指针（即遍历器）g。</strong> 这是Generator函数不同于普通函数的另一个地方，<strong>即执行它（调用函数）不会返回结果</strong>， 返回的一个指针对象 。<strong>调用指针g的next方法，会移动内部指针（即执行异步任务的第一阶段），指向第一个遇到的yield语句，</strong>这里我们是x + 2，但是实际上这里只是举例，实际上 x + 2 这句应该是一个异步操作，比如ajax请求。 <strong>换言之，next</strong>方法的作用是分阶段执行Generator函数。每次调用next方法，会返回一个对象，表示当前阶段的信息（value属性和done属性）。 value属性是yield语句后面表达式的值，表示当前阶段的值；done属性是一个布尔值，表示Generator函数是否执行完毕，即是否还有下一个阶段。</p>
<p><strong>Generator函数的数据交换和错误处理</strong></p>
<p>　　Generator 函数可以暂停执行和恢复执行，这是它能封装异步任务的根本原因。除此之外，它还有两个特性，使它可以作为异步编程的完整解决方案：函数体内外的数据交换和错误处理机制。</p>
<p>　　<code>next</code>返回值的value属性，是 Generator 函数向外输出数据；<code>next</code>方法还可以接受参数，向 Generator 函数体内输入数据。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">function* gen(x)&#123;</span><br><span class="line">  var y &#x3D; yield x + 2;</span><br><span class="line">  return y;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">var g &#x3D; gen(1);</span><br><span class="line">g.next() &#x2F;&#x2F; &#123; value: 3, done: false &#125;</span><br><span class="line">g.next(2) &#x2F;&#x2F; &#123; value: 2, done: true &#125;</span><br></pre></td></tr></table></figure>

<p>　　上面代码中，第一<code>next</code>方法的<code>value</code>属性，返回表达式<code>x + 2</code>的值<code>3</code>。第二个<code>next</code>方法带有参数<code>2</code>，这个参数可以传入 Generator 函数，作为上个阶段异步任务的返回结果，被函数体内的变量<code>y</code>接收。因此，这一步的<code>value</code>属性，返回的就是<code>2</code>（变量<code>y</code>的值）。</p>
<p>Generator 函数内部还可以部署错误处理代码，捕获函数体外抛出的错误。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">function* gen(x)&#123;</span><br><span class="line">  try &#123;</span><br><span class="line">    var y &#x3D; yield x + 2;</span><br><span class="line">  &#125; catch (e)&#123;</span><br><span class="line">    console.log(e);</span><br><span class="line">  &#125;</span><br><span class="line">  return y;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">var g &#x3D; gen(1);</span><br><span class="line">g.next();</span><br><span class="line">g.throw(&#39;出错了&#39;);</span><br><span class="line">&#x2F;&#x2F; 出错了</span><br></pre></td></tr></table></figure>

<p>上面代码的最后一行，Generator 函数体外，使用指针对象的<code>throw</code>方法抛出的错误，可以被函数体内的<code>try...catch</code>代码块捕获。这意味着，出错的代码与处理错误的代码，实现了时间和空间上的分离，这对于异步编程无疑是很重要的。</p>
<p><strong>异步任务的封装****下面看看如何使用 Generator 函数，执行一个真实的异步任务。</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">var fetch &#x3D; require(&#39;node-fetch&#39;);</span><br><span class="line"></span><br><span class="line">function* gen()&#123;</span><br><span class="line">  var url &#x3D; &#39;https:&#x2F;&#x2F;api.github.com&#x2F;users&#x2F;github&#39;;</span><br><span class="line">  var result &#x3D; yield fetch(url);</span><br><span class="line">  console.log(result.bio);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>　　上面代码中，Generator 函数封装了一个异步操作，该操作先读取一个远程接口，然后从 JSON 格式的数据解析信息。就像前面说过的，这段代码非常像同步操作，除了加上了<code>yield</code>命令。</p>
<p>　　执行这段代码的方法如下。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">var g &#x3D; gen();</span><br><span class="line">var result &#x3D; g.next();</span><br><span class="line"></span><br><span class="line">result.value.then(function(data)&#123;</span><br><span class="line">  return data.json();</span><br><span class="line">&#125;).then(function(data)&#123;</span><br><span class="line">  g.next(data);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>　　上面代码中，首先执行 Generator 函数，获取遍历器对象，然后使用<code>next</code>方法（第二行），执行异步任务的第一阶段。由于<code>Fetch</code>模块返回的是一个 Promise 对象，因此要用<code>then</code>方法调用下一个<code>next</code>方法。</p>
<p>　　可以看到，虽然 Generator 函数将异步操作表示得很简洁，但是流程管理却不方便（即何时执行第一阶段、何时执行第二阶段）。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">function* gen(x) &#123;</span><br><span class="line">  yield 1;</span><br><span class="line">  yield 2;</span><br><span class="line">  yield 3;</span><br><span class="line">  return 4;</span><br><span class="line">&#125;</span><br><span class="line">var a &#x3D; gen();</span><br><span class="line">console.log(a.next());</span><br><span class="line">console.log(a.next());</span><br><span class="line">console.log(a.next());</span><br><span class="line">console.log(a.next());</span><br></pre></td></tr></table></figure>

<p>　　最终，打印台输出</p>
<p><img src="/%E6%B7%B1%E5%85%A5%E6%8E%A2%E7%A9%B6JavaScript.assets/1044137-20170831143725077-1955052959.png" alt="img"></p>
<p>即开始调用gen()，并没有真正的调用，而是<strong>返回了一个生成器对象</strong>，a.next()的时候，执行第一个yield，并立刻暂停执行，交出了控制权； 接着，我们就可以去a.next() 开始恢复执行。。。 如此循环往复。　　</p>
<p><strong>每当调用生成器对象的next的方法时，就会运行到下一个yield表达式。 之所以称这里的gen（）为生成器函数，是因为区别如下：</strong></p>
<ul>
<li><strong>普通函数使用function来声明，而生成器函数使用 function * 来声明</strong>。</li>
<li><strong>普通函数使用return来返回值，而生成器函数使用yield来返回值。</strong></li>
<li><strong>普通函数式run to completion模式 ，即一直运行到末尾； 而生成器函数式 run-pause-run 模式， 函数可以在执行过程中暂停一次或者多次。并且暂停期间允许其他代码执行。</strong></li>
</ul>
<h2 id="async-await"><a href="#async-await" class="headerlink" title="async/await"></a>async/await</h2><p>async函数基于Generator又做了几点改进：</p>
<ul>
<li>内置执行器，将Generator函数和自动执行器进一步包装。</li>
<li>语义更清楚，async表示函数中有异步操作，await表示等待着紧跟在后边的表达式的结果。</li>
<li>适用性更广泛，await后面可以跟promise对象和原始类型的值(Generator中不支持)</li>
</ul>
<p>　　很多人都认为这是异步编程的终极解决方案，由此评价就可知道该方法有多优秀了。它基于Promise使用async/await来优化then链的调用,其实也是Generator函数的语法糖。 async 会将其后的函数（函数表达式或 Lambda）的返回值封装成一个 Promise 对象，而 await 会等待这个 Promise 完成，并将其 resolve 的结果返回出来。</p>
<p>　　await得到的就是返回值，其内部已经执行promise中resolve方法，然后将结果返回。使用async/await的方式写回调任务：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">async function dolt()&#123;</span><br><span class="line">    console.time(&#39;dolt&#39;);</span><br><span class="line">    const time1&#x3D;300;</span><br><span class="line">    const time2&#x3D;await step1(time1);</span><br><span class="line">    const time3&#x3D;await step2(time2);</span><br><span class="line">    const result&#x3D;await step3(time3);</span><br><span class="line">    console.log(&#96;result is $&#123;result&#125;&#96;);</span><br><span class="line">    console.timeEnd(&#39;dolt&#39;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">dolt();</span><br></pre></td></tr></table></figure>

<p>　　可以看到，在使用await关键字所在的函数一定要是async关键字修饰的。</p>
<p>　　功能还很新，属于ES7的语法，但使用Babel插件可以很好的转义。另外<strong>await只能用在async函数中，否则会报错</strong></p>
<h1 id="JS的事件执行机制"><a href="#JS的事件执行机制" class="headerlink" title="JS的事件执行机制"></a>JS的事件执行机制</h1><h2 id="一、js的内存模型"><a href="#一、js的内存模型" class="headerlink" title="一、js的内存模型"></a><strong>一、js的内存模型</strong></h2><p><strong><img src="/%E6%B7%B1%E5%85%A5%E6%8E%A2%E7%A9%B6JavaScript.assets/1760011-20200512143232426-796587478.png" alt="img"></strong></p>
<h2 id=""><a href="#" class="headerlink" title=""></a><strong><img src="/%E6%B7%B1%E5%85%A5%E6%8E%A2%E7%A9%B6JavaScript.assets/1760011-20200512143348561-1197833870.png" alt="img"></strong></h2><h2 id="二、js代码执行机制："><a href="#二、js代码执行机制：" class="headerlink" title="二、js代码执行机制："></a><strong>二、js代码执行机制：</strong></h2><ul>
<li><h3 id="所有同步任务都在主线程上的栈中执行。"><a href="#所有同步任务都在主线程上的栈中执行。" class="headerlink" title="所有同步任务都在主线程上的栈中执行。"></a>所有同步任务都在主线程上的栈中执行。</h3></li>
<li><h3 id="主线程之外，还存在一个”任务队列”（task-queue）。只要异步任务有了运行结果，就在”任务队列”之中放置一个事件。"><a href="#主线程之外，还存在一个”任务队列”（task-queue）。只要异步任务有了运行结果，就在”任务队列”之中放置一个事件。" class="headerlink" title="主线程之外，还存在一个”任务队列”（task queue）。只要异步任务有了运行结果，就在”任务队列”之中放置一个事件。"></a>主线程之外，还存在一个”任务队列”（task queue）。只要异步任务有了运行结果，就在”任务队列”之中放置一个事件。</h3></li>
<li><h3 id="一旦”栈”中的所有同步任务执行完毕，系统就会读取”任务队列”，选择出需要首先执行的任务（由浏览器决定，并不按序）。"><a href="#一旦”栈”中的所有同步任务执行完毕，系统就会读取”任务队列”，选择出需要首先执行的任务（由浏览器决定，并不按序）。" class="headerlink" title="一旦”栈”中的所有同步任务执行完毕，系统就会读取”任务队列”，选择出需要首先执行的任务（由浏览器决定，并不按序）。"></a>一旦”栈”中的所有同步任务执行完毕，系统就会读取”任务队列”，选择出需要首先执行的任务（由浏览器决定，并不按序）。</h3></li>
</ul>
<h2 id="三、宏任务与微任务："><a href="#三、宏任务与微任务：" class="headerlink" title="三、宏任务与微任务："></a><strong>三、宏任务与微任务：</strong></h2><ol>
<li><h3 id="MacroTask（宏观Task）-setTimeout-setInterval-requestAnimationFrame（请求动画）-I-O"><a href="#MacroTask（宏观Task）-setTimeout-setInterval-requestAnimationFrame（请求动画）-I-O" class="headerlink" title="MacroTask（宏观Task） setTimeout, setInterval, , requestAnimationFrame（请求动画）, I/O"></a>MacroTask（宏观Task） <strong>setTimeout, setInterval</strong>, , requestAnimationFrame（请求动画）, I/O</h3></li>
<li><h3 id="MicroTask（微观任务）-process-nextTick-Promise-Object-observe-MutationObserver"><a href="#MicroTask（微观任务）-process-nextTick-Promise-Object-observe-MutationObserver" class="headerlink" title="MicroTask（微观任务） process.nextTick, Promise, Object.observe, MutationObserver"></a>MicroTask（微观任务） process.nextTick, <strong>Promise</strong>, Object.observe, MutationObserver</h3></li>
<li><h3 id="先同步-再取出第一个宏任务执行-所有的相关微任务总会在下一个宏任务之前全部执行完毕-如果遇见-就-先微后宏"><a href="#先同步-再取出第一个宏任务执行-所有的相关微任务总会在下一个宏任务之前全部执行完毕-如果遇见-就-先微后宏" class="headerlink" title="先同步 再取出第一个宏任务执行 所有的相关微任务总会在下一个宏任务之前全部执行完毕 如果遇见 就 先微后宏"></a><strong>先同步 再取出第一个宏任务执行 所有的相关微任务总会在下一个宏任务之前全部执行完毕 如果遇见 就 先微后宏</strong></h3></li>
</ol>
<h3 id="案例一：（在主线程上添加宏任务）"><a href="#案例一：（在主线程上添加宏任务）" class="headerlink" title="案例一：（在主线程上添加宏任务）"></a><strong>案例一：（在主线程上添加宏任务）</strong></h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">console</span>.log(<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">&#125;,<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">3</span>) <span class="comment">//1 3 2</span></span><br></pre></td></tr></table></figure>

<p>先看代码：一个打印，一个定时器，一个打印</p>
<p>因为<strong>定时器是异步操作，又是宏任务，</strong>所以先执行第一个打印，接着<strong>将setTimeout放入宏任务队列</strong>，接着执行第二个打印，再执行宏任务队列中的setTimeout</p>
<h3 id="案例二：（在主线程上添加微任务）"><a href="#案例二：（在主线程上添加微任务）" class="headerlink" title="案例二：（在主线程上添加微任务）"></a>案例二：（在主线程上添加微任务）</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="number">1</span>)</span><br><span class="line"> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve,reject</span>)</span>&#123;</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">'2'</span>)</span><br><span class="line">     resolve()</span><br><span class="line"> &#125;).then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="number">3</span>)</span><br><span class="line"> &#125;)</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="number">4</span>)  <span class="comment">//1 2 4 3</span></span><br></pre></td></tr></table></figure>

<p>先看代码：一个打印，一个new promise,一个promise.then，一个打印</p>
<p>因为<strong>new promise会立即执行，promise.then是异步操作且是微任务</strong></p>
<p>所以，先执行第一个打印，执行new Promise，<strong>将promise.then放入微任务队列</strong>，接着执行第二个打印，再执行微任务队列中的promise.then</p>
<h3 id="案例三：（宏任务中创建微任务）"><a href="#案例三：（宏任务中创建微任务）" class="headerlink" title="案例三：（宏任务中创建微任务）"></a>案例三：（宏任务中创建微任务）</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">'1'</span>);</span><br><span class="line"> </span><br><span class="line"> setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">'2'</span>);</span><br><span class="line">   <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> (<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">'3'</span>);</span><br><span class="line">     resolve();</span><br><span class="line">   &#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">'4'</span>)</span><br><span class="line">   &#125;)</span><br><span class="line"> &#125;,<span class="number">0</span>)</span><br><span class="line">  </span><br><span class="line"> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> (<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">'5'</span>);</span><br><span class="line">   resolve();</span><br><span class="line"> &#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">'6'</span>)</span><br><span class="line"> &#125;)</span><br><span class="line"></span><br><span class="line"> setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">'7'</span>);</span><br><span class="line">   <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> (<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">'8'</span>);</span><br><span class="line">     resolve();</span><br><span class="line">   &#125;).then(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">'9'</span>)</span><br><span class="line">   &#125;)</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">'10'</span>)</span><br><span class="line"> &#125;,<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'11'</span>)</span><br></pre></td></tr></table></figure>

<p>// 1 5 11 6 2 3 4 7 8 10 9</p>
<p>先看代码：一个打印，第一个定时器，一个new promise,一个promise.then,第二个定时器，一个打印</p>
<p><strong>定时器是异步操作，又是宏任务，*<em>promise.then是异步操作且是微任务*</em></strong></p>
<p><strong>所以，先执行第一个打印（1），将第一个定时器放入宏任务队列，执行new Promise（5），将promise.then放入微任务队列，将第二个定时器放入宏任务队列，执行打印（11）；</strong></p>
<p><strong>主线程上的代码执行完毕后，看是否有微任务？此时：微任务队列中有一个promise.then,执行它（6）；微任务执行完毕看宏任务队列；</strong></p>
<p><strong>此时宏任务队列中两个定时器，延时都是0秒，所以按顺序执行就ok,先执行第一个定时器</strong></p>
<p><strong>第一个定时器中：一个打印，一个mew promise,一个promise.then(微任务)；****（宏任务中包含微任务，一定要将宏任务中的微任务执行完，再去执行下一个宏任务）</strong></p>
<p>先执行打印（2），再执行new promise(3),**再执行promise.then(**4);第一个宏任务执行完，执行第二个宏任务（第二个定时器）</p>
<p><strong>第二个定时器中：一个打印，一个new promise，一个promise.then(微任务),一个打印</strong></p>
<p><strong>先执行第一个打印（7），再执行new promise(8),再执行第二个打印（10），在执行promise.then（9）</strong>　</p>
<h3 id="案例四：（微任务中创建宏任务）"><a href="#案例四：（微任务中创建宏任务）" class="headerlink" title="案例四：（微任务中创建宏任务）"></a><strong>案例四：（微任务中创建宏任务）</strong></h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">"1"</span>)</span><br><span class="line">   resolve()</span><br><span class="line"> &#125;).then(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">"2"</span>)</span><br><span class="line">   setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">"3"</span>)</span><br><span class="line">   &#125;,<span class="number">0</span>)</span><br><span class="line"> &#125;)</span><br><span class="line"> setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">   <span class="built_in">console</span>.log(<span class="string">"4"</span>)</span><br><span class="line"> &#125;,<span class="number">1000</span>)</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"5"</span>)  <span class="comment">//1 5 2 3 4</span></span><br></pre></td></tr></table></figure>

<p>先看代码：一个new promise,（一个then,一个定时器（0秒）），一个定时器（1秒），一个打印 <strong>微任务中有宏任务，则将宏任务放入宏任务队列任务中</strong></p>
<p>先执行new promise(1),<strong>再将promise.then放入微任务队列，将定时器放入宏任务队列（0秒），将定时器放入宏任务队列（1秒）</strong>，执行打印(5)</p>
<p>接着看微任务队列，执行promise.then(2);微任务队列中都执行完再看宏任务队列</p>
<p>宏任务队列中两个定时器，一个延时0秒，一个延时1秒，所以先执行延时0秒的那个</p>
<p>第一个定时器：执行（3）；</p>
<p>第二个定时器：执行（4）</p>
<h1 id="JS事件执行"><a href="#JS事件执行" class="headerlink" title="JS事件执行"></a>JS事件执行</h1><p>本文是承接<a href="https://www.jianshu.com/p/5b1db8806e80" target="_blank" rel="noopener">Promise</a>来说的，大家都知道，JavaScript脚本是单线程的语言，虽然有H5的Web-Worker加持，但是创建出来的子线程完全受主线程控制，且不得操作DOM，所以还是无法改变JavaScript单线程的本质</p>
<blockquote>
<p>JavaScript是单线程执行的，无法同时执行多段代码。当某一段代码正在执行的时候，所有后续的任务都必须等待，形成一个队列。一旦当前任务执行完毕，再从队列中取出下一个任务，这也常被称为 “阻塞式执行”。所以一次鼠标点击，或是计时器到达时间点，或是Ajax请求完成触发了回调函数，这些事件处理程序或回调函数都不会立即运行，而是立即排队，一旦线程有空闲就执行。假如当前JavaScript线程正在执行一段很耗时的代码，此时发生了一次鼠标点击，那么事件处理程序就被阻塞，用户也无法立即看到反馈，事件处理程序会被放入任务队列，直到前面的代码结束以后才会开始执行。如果代码中设定了一个setTimeout，那么浏览器便会在合适的时间，将代码插入任务队列，如果这个时间设为0，就代表立即插入队列，但不是立即执行，仍然要等待前面代码执行完毕。所以 setTimeout 并不能保证执行的时间，是否及时执行取决于JavaScript 线程是拥挤还是空闲。</p>
</blockquote>
<p>这里就涉及到了执行栈(Stack)和队列任务(Queue Task)的概念，将同步任务都放入主线程的Stack当中，将异步和延时的任务都放入Event Queue里面等待执行，Event Queue即为事件队列，所包含的全是事件，等执行栈为空之后就代表主线程执行完毕，再去Event Queue中读取第一个事件放入主线程，执行完毕再读取第二个…因此形成一个JavaScript的Event Loop(事件循环)，Event Loop就是JavaScript的实现异步的一种方式，也是JavaScript的执行机制。</p>
<p>至于定时器(timer)嘛，因为里面的参数有一个是回调函数，另一个是延时执行的毫秒数，所以他也要放进队列中，而上面的引用部分有个延时0毫秒，它的含义就是立即放入队列，而不是立即放进执行栈执行；JavaScript还有一种函数叫做回调函数，阮一峰大神是这么说的：</p>
<blockquote>
<p>所谓”回调函数”（callback），就是那些会被主线程挂起来的代码。异步任务必须指定回调函数，当主线程开始执行异步任务，就是执行对应的回调函数。</p>
</blockquote>
<p>下面这幅图是从别人那里偷来的(ps:主要这幅图太有说服力度了，不信你看)：</p>
<p>![img](https:////upload-images.jianshu.io/upload_images/8560482-92ec4b6e10c45e30.png?imageMogr2/auto-orient/strip|imageView2/2/w/601/format/webp</p>
<p>nodeJs里面提出了和任务队列有关联的方法<code>process.nextTick(callback)</code>，它的含义是本次循环完毕等到下一次循环开始再执行，也就是在当前执行栈的尾部。</p>
<p>在网上经常看到这样的关键字，从广义上来讲，我们弄明白了同步异步，但是狭义上来说还有两个新的概念，其实这个概念我还真不确定官方是否同意，我是看到<a href="https://links.jianshu.com/go?to=https://juejin.im/post/5a6fd5ce6fb9a01c9406208d" target="_blank" rel="noopener">闹闹不爱闹</a>在掘金中阐明的:</p>
<blockquote>
<ol>
<li>宏任务macro task [ˈmækrəʊ]：当前调用栈中执行的代码成为宏任务。（主代码快，定时器等等）。exp:script（全局任务），setTimeout ，setInterval ，setImmediate ，I/O ，UI rendering</li>
<li>微任务micro task [ˈmaɪkrəʊ]： 当前（此次事件循环中）宏任务执行完，在下一个宏任务开始之前需要执行的任务,可以理解为回调事件。（promise.then，proness.nextTick等等）。exp:process.nextTick，promise,Object.observer,MutationObserver</li>
<li>宏任务中的事件放在callback queue中，由事件触发线程维护；微任务的事件放在微任务队列中，由js引擎线程维护。</li>
</ol>
</blockquote>
<p>不管这个东西存不存在，既然国人都这么叫了，那我是这么理解的：<br> 他们口中的宏观任务就是我们的回调函数，宏观任务和微观任务就是我们的Event Queue，执行栈执行完毕会执行微观任务再执行宏观任务，我不建议大家继续这么称呼，其实macro task和micro task都属于是浏览器执行js的执行机制，这个我不是为了较真，估计我也是被我们公司的老总教训的太多了，不去不去怕了怕了o((⊙﹏⊙))o….</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'setTimeout'</span>);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="built_in">Promise</span>.resolve(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'resolve'</span>);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'promise'</span>);</span><br><span class="line">    resolve();</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'then'</span>);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">'console'</span>);</span><br></pre></td></tr></table></figure>

<p>其实这个栗字很简单，进入script主线程，遇到setTimeout push到macro task，遇到resolve push到macro task，new Promise立即执行，率先打印，then push到micro task，接着第二个打印console，然后执行micro task打印出then，接着执行macro task打印出setTimeout，因为Promise.resolve这个回到函数未调用，有的浏览器报undefined，有的不打印。</p>
<p>到了这里就差不多了，为了帮助大家彻底吃透它，再来一剂猛药：</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">'1'</span>);</span><br><span class="line">setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'9'</span>);</span><br><span class="line">    <span class="keyword">this</span>.$nextTick(<span class="function"><span class="params">()</span> =&gt;</span>  &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'11'</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'10'</span>);</span><br><span class="line">        resolve();</span><br><span class="line">    &#125;).then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'12'</span>)</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;,<span class="number">5000</span>);</span><br><span class="line"><span class="keyword">this</span>.$nextTick(<span class="function"><span class="params">()</span> =&gt;</span>  &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'3'</span>);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'2'</span>);</span><br><span class="line">    resolve();</span><br><span class="line">&#125;).then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'4'</span>);</span><br><span class="line">&#125;);</span><br><span class="line">setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'5'</span>);</span><br><span class="line">    <span class="keyword">this</span>.$nextTick(<span class="function"><span class="params">()</span> =&gt;</span>  &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'7'</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve</span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'6'</span>);</span><br><span class="line">        resolve();</span><br><span class="line">    &#125;).then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'8'</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>看到诸多异步延时任务先不要慌，一步一步来解读，代码中的this.$nextTick(callback)千万不要解读成上面的process.nextTick(callback)，否则你会被坑惨的，process是nodeJs里面的，nodeJs执行机制和JavaScript的执行机制是不同的，nodeJs不会看你代码的层级关系哦，只关心你的事件的类型，按照这个顺序来执行代码，而我们的js是按照父级的事件，有着层级关系的执行。<br> vueJs的主线程先执行，首先打印出1，第一个setTimeout push到macro task，nextTick放入micro task，Promise立即执行，then push进micro task，第二个setTimeout push到macro task，接着执行micro task，打印3 4，最后执行macro task，注意这里有个坑，macro task里面有两个timer，第一个5000ms之后执行，所以先执行第二个，所以最后的答案小学生都知道，打印顺序从1到12。</p>
<h1 id="防抖函数"><a href="#防抖函数" class="headerlink" title="防抖函数"></a>防抖函数</h1><h2 id="一、函数为什么要防抖"><a href="#一、函数为什么要防抖" class="headerlink" title="一、函数为什么要防抖"></a>一、函数为什么要防抖</h2><p>有如下代码</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">window</span>.onresize = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'触发窗口监听回调函数'</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当我们在PC上缩放浏览器窗口时，一秒可以轻松触发30次事件。手机端触发其他Dom时间监听回调时同理。</p>
<p>这里的回调函数只是打印字符串，如果回调函数更加复杂，可想而知浏览器的压力会非常大，用户体验会很糟糕。</p>
<p><code>resize</code>或<code>scroll</code>等Dom事件的监听回调会被频繁触发，因此我们要对其进行限制。</p>
<h2 id="二、实现思路"><a href="#二、实现思路" class="headerlink" title="二、实现思路"></a>二、实现思路</h2><p>函数去抖简单来说就是对于一定时间段的连续的函数调用，只让其执行一次，初步的实现思路如下：</p>
<p>第一次调用函数，创建一个定时器，在指定的时间间隔之后运行代码。当第二次调用该函数时，它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了，这个操作就没有任何意义。然而，如果前一个定时器尚未执行，其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。</p>
<h2 id="三、Debounce-应用场景"><a href="#三、Debounce-应用场景" class="headerlink" title="三、Debounce 应用场景"></a>三、Debounce 应用场景</h2><ul>
<li>每次 resize/scroll 触发统计事件</li>
<li>文本输入的验证（连续输入文字后发送 AJAX 请求进行验证，验证一次就好）</li>
</ul>
<h2 id="四、函数防抖最终版"><a href="#四、函数防抖最终版" class="headerlink" title="四、函数防抖最终版"></a>四、函数防抖最终版</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, wait, immediate</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> timeout</span><br><span class="line">  <span class="comment">// debounced函数为返回值</span></span><br><span class="line">  <span class="comment">// 使用Async/Await处理异步，如果函数异步执行，等待setTimeout执行完，拿到原函数返回值后将其返回</span></span><br><span class="line">  <span class="comment">// args为返回函数调用时传入的参数，传给method</span></span><br><span class="line">  <span class="keyword">let</span> debounced = <span class="function"><span class="keyword">function</span>(<span class="params">...args</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span> (<span class="function"><span class="params">resolve</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 用于记录原函数执行结果</span></span><br><span class="line">      <span class="keyword">let</span> result</span><br><span class="line">      <span class="comment">// 将method执行时this的指向设为debounce返回的函数被调用时的this指向</span></span><br><span class="line">      <span class="keyword">let</span> context = <span class="keyword">this</span></span><br><span class="line">      <span class="comment">// 如果存在定时器则将其清除</span></span><br><span class="line">      <span class="keyword">if</span> (timeout) &#123;</span><br><span class="line">        clearTimeout(timeout)</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">// 立即执行需要两个条件，一是immediate为true，二是timeout未被赋值或被置为null</span></span><br><span class="line">      <span class="keyword">if</span> (immediate) &#123;</span><br><span class="line">        <span class="comment">// 如果定时器不存在，则立即执行，并设置一个定时器，wait毫秒后将定时器置为null</span></span><br><span class="line">        <span class="comment">// 这样确保立即执行后wait毫秒内不会被再次触发</span></span><br><span class="line">        <span class="keyword">let</span> callNow = !timeout</span><br><span class="line">        timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">          timeout = <span class="literal">null</span></span><br><span class="line">        &#125;, wait)</span><br><span class="line">        <span class="comment">// 如果满足上述两个条件，则立即执行并记录其执行结果</span></span><br><span class="line">        <span class="keyword">if</span> (callNow) &#123;</span><br><span class="line">          result = method.apply(context, args)</span><br><span class="line">          resolve(result)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">// 如果immediate为false，则等待函数执行并记录其执行结果</span></span><br><span class="line">        <span class="comment">// 并将Promise状态置为fullfilled，以使函数继续执行</span></span><br><span class="line">        timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">          <span class="comment">// args是一个数组，所以使用fn.apply</span></span><br><span class="line">          <span class="comment">// 也可写作method.call(context, ...args)</span></span><br><span class="line">          result = method.apply(context, args)</span><br><span class="line">          resolve(result)</span><br><span class="line">        &#125;, wait)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 在返回的debounced函数上添加取消方法</span></span><br><span class="line">  debounced.cancel = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    clearTimeout(timeout)</span><br><span class="line">    timeout = <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> debounced</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>需要注意的是，如果需要原函数返回值，调用防抖后的函数的外层函数需要使用Async/Await语法等待执行结果返回</p>
<p>使用方法见代码：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">square</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">Math</span>.pow(num, <span class="number">2</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> debouncedFn = debounce(square, <span class="number">1000</span>, <span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">window</span>.addEventListener(<span class="string">'resize'</span>, <span class="keyword">async</span> () =&gt; &#123;</span><br><span class="line">  <span class="keyword">let</span> val</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    val = <span class="keyword">await</span> debouncedFn(<span class="number">4</span>)</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="built_in">console</span>.error(err)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 停止缩放1S后输出：</span></span><br><span class="line">  <span class="comment">// 原函数的返回值为：16</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">`原函数返回值为<span class="subst">$&#123;val&#125;</span>`</span>)</span><br><span class="line">&#125;, <span class="literal">false</span>)</span><br></pre></td></tr></table></figure>

<p>具体的实现步骤请往下看</p>
<h2 id="五、Debounce-的实现"><a href="#五、Debounce-的实现" class="headerlink" title="五、Debounce 的实现"></a>五、Debounce 的实现</h2><h3 id="1-《JavaScript高级程序设计》（第三版）中的实现"><a href="#1-《JavaScript高级程序设计》（第三版）中的实现" class="headerlink" title="1. 《JavaScript高级程序设计》（第三版）中的实现"></a>1. 《JavaScript高级程序设计》（第三版）中的实现</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, context</span>) </span>&#123;</span><br><span class="line">  clearTimeout(method.tId)</span><br><span class="line">  method.tId = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    method.call(context)</span><br><span class="line">  &#125;, <span class="number">1000</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">print</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'Hello World'</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">window</span>.onresize = debounce(print)</span><br></pre></td></tr></table></figure>

<p>我们不停缩放窗口，当停止1S后，打印出Hello World。</p>
<p><strong>有个可以优化的地方</strong>: 此实现方法有副作用（Side Effect），改变了输入值（method），给method新增了属性</p>
<h3 id="2-优化第一版：消除副作用，将定时器隔离"><a href="#2-优化第一版：消除副作用，将定时器隔离" class="headerlink" title="2. 优化第一版：消除副作用，将定时器隔离"></a>2. 优化第一版：消除副作用，将定时器隔离</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, wait, context</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> timeout</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (timeout) &#123;</span><br><span class="line">      clearTimeout(timeout)</span><br><span class="line">    &#125;</span><br><span class="line">    timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">      method.call(context)</span><br><span class="line">    &#125;, wait)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="3-优化第二版：自动调整this正确指向"><a href="#3-优化第二版：自动调整this正确指向" class="headerlink" title="3. 优化第二版：自动调整this正确指向"></a>3. 优化第二版：自动调整this正确指向</h3><p>之前的函数我们需要手动传入函数执行上下文<code>context</code>，现在优化将 this 指向正确的对象。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, wait</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> timeout</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 将method执行时this的指向设为debounce返回的函数被调用时的this指向</span></span><br><span class="line">    <span class="keyword">let</span> context = <span class="keyword">this</span></span><br><span class="line">    <span class="keyword">if</span> (timeout) &#123;</span><br><span class="line">      clearTimeout(timeout)</span><br><span class="line">    &#125;</span><br><span class="line">    timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">      method.call(context)</span><br><span class="line">    &#125;, wait)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="4-优化第三版：函数可传入参数"><a href="#4-优化第三版：函数可传入参数" class="headerlink" title="4. 优化第三版：函数可传入参数"></a>4. 优化第三版：函数可传入参数</h3><p>即便我们的函数不需要传参，但是别忘了JavaScript 在事件处理函数中会提供事件对象 event，所以我们要实现传参功能。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, wait</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> timeout</span><br><span class="line">  <span class="comment">// args为返回函数调用时传入的参数，传给method</span></span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">...args</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> context = <span class="keyword">this</span></span><br><span class="line">    <span class="keyword">if</span> (timeout) &#123;</span><br><span class="line">      clearTimeout(timeout)</span><br><span class="line">    &#125;</span><br><span class="line">    timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// args是一个数组，所以使用fn.apply</span></span><br><span class="line">      <span class="comment">// 也可写作method.call(context, ...args)</span></span><br><span class="line">      method.apply(context, args)</span><br><span class="line">    &#125;, wait)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="5-优化第四版：提供立即执行选项"><a href="#5-优化第四版：提供立即执行选项" class="headerlink" title="5. 优化第四版：提供立即执行选项"></a>5. 优化第四版：提供立即执行选项</h3><p>有些时候我不希望非要等到事件停止触发后才执行，我希望立刻执行函数，然后等到停止触发n毫秒后，才可以重新触发执行。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, wait, immediate</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> timeout</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">...args</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> context = <span class="keyword">this</span></span><br><span class="line">    <span class="keyword">if</span> (timeout) &#123;</span><br><span class="line">      clearTimeout(timeout)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 立即执行需要两个条件，一是immediate为true，二是timeout未被赋值或被置为null</span></span><br><span class="line">    <span class="keyword">if</span> (immediate) &#123;</span><br><span class="line">      <span class="comment">// 如果定时器不存在，则立即执行，并设置一个定时器，wait毫秒后将定时器置为null</span></span><br><span class="line">      <span class="comment">// 这样确保立即执行后wait毫秒内不会被再次触发</span></span><br><span class="line">      <span class="keyword">let</span> callNow = !timeout</span><br><span class="line">      timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">        timeout = <span class="literal">null</span></span><br><span class="line">      &#125;, wait)</span><br><span class="line">      <span class="keyword">if</span> (callNow) &#123;</span><br><span class="line">        method.apply(context, args)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">// 如果immediate为false，则函数wait毫秒后执行</span></span><br><span class="line">      timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// args是一个类数组对象，所以使用fn.apply</span></span><br><span class="line">        <span class="comment">// 也可写作method.call(context, ...args)</span></span><br><span class="line">        method.apply(context, args)</span><br><span class="line">      &#125;, wait)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="6-优化第五版：提供取消功能"><a href="#6-优化第五版：提供取消功能" class="headerlink" title="6. 优化第五版：提供取消功能"></a>6. 优化第五版：提供取消功能</h3><p>有些时候我们需要在不可触发的这段时间内能够手动取消防抖，代码实现如下：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, wait, immediate</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> timeout</span><br><span class="line">  <span class="comment">// 将返回的匿名函数赋值给debounced，以便在其上添加取消方法</span></span><br><span class="line">  <span class="keyword">let</span> debounced = <span class="function"><span class="keyword">function</span>(<span class="params">...args</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> context = <span class="keyword">this</span></span><br><span class="line">    <span class="keyword">if</span> (timeout) &#123;</span><br><span class="line">      clearTimeout(timeout)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (immediate) &#123;</span><br><span class="line">      <span class="keyword">let</span> callNow = !timeout</span><br><span class="line">      timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">        timeout = <span class="literal">null</span></span><br><span class="line">      &#125;, wait)</span><br><span class="line">      <span class="keyword">if</span> (callNow) &#123;</span><br><span class="line">        method.apply(context, args)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">        method.apply(context, args)</span><br><span class="line">      &#125;, wait)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 加入取消功能，使用方法如下</span></span><br><span class="line">  <span class="comment">// let myFn = debounce(otherFn)</span></span><br><span class="line">  <span class="comment">// myFn.cancel()</span></span><br><span class="line">  debounced.cancel = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    clearTimeout(timeout)</span><br><span class="line">    timeout = <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>至此，我们已经比较完整地实现了一个underscore中的debounce函数。</p>
<h2 id="六、遗留问题"><a href="#六、遗留问题" class="headerlink" title="六、遗留问题"></a>六、遗留问题</h2><p>需要防抖的函数可能是存在返回值的，我们要对这种情况进行处理，<code>underscore</code>的处理方法是将函数返回值在返回的<code>debounced</code>函数内再次返回，但是这样其实是有问题的。如果参数<code>immediate</code>传入值不为<code>true</code>的话，当防抖后的函数第一次被触发时，如果原始函数有返回值，其实是拿不到返回值的，因为原函数是在<code>setTimeout</code>内，是异步延迟执行的，而<code>return</code>是同步执行的，所以返回值是<code>undefined</code>。</p>
<p>第二次触发时拿到的返回值其实是第一次执行的返回值，第三次触发时拿到的返回值其实是第二次执行的返回值，以此类推。</p>
<h3 id="1-使用回调函数处理函数返回值"><a href="#1-使用回调函数处理函数返回值" class="headerlink" title="1. 使用回调函数处理函数返回值"></a>1. 使用回调函数处理函数返回值</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, wait, immediate, callback</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> timeout, result</span><br><span class="line">  <span class="keyword">let</span> debounced = <span class="function"><span class="keyword">function</span>(<span class="params">...args</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> context = <span class="keyword">this</span></span><br><span class="line">    <span class="keyword">if</span> (timeout) &#123;</span><br><span class="line">      clearTimeout(timeout)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (immediate) &#123;</span><br><span class="line">      <span class="keyword">let</span> callNow = !timeout</span><br><span class="line">      timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">        timeout = <span class="literal">null</span></span><br><span class="line">      &#125;, wait)</span><br><span class="line">      <span class="keyword">if</span> (callNow) &#123;</span><br><span class="line">        result = method.apply(context, args)</span><br><span class="line">        <span class="comment">// 使用回调函数处理函数返回值</span></span><br><span class="line">        callback &amp;&amp; callback(result)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">        result = method.apply(context, args)</span><br><span class="line">        <span class="comment">// 使用回调函数处理函数返回值</span></span><br><span class="line">        callback &amp;&amp; callback(result)</span><br><span class="line">      &#125;, wait)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  debounced.cancel = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    clearTimeout(timeout)</span><br><span class="line">    timeout = <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> debounced</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样我们就可以在函数防抖时传入一个回调函数来处理函数的返回值，使用代码如下：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">square</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">Math</span>.pow(num, <span class="number">2</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> debouncedFn = debounce(square, <span class="number">1000</span>, <span class="literal">false</span>, val =&gt; &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">`原函数的返回值为：<span class="subst">$&#123;val&#125;</span>`</span>)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="built_in">window</span>.addEventListener(<span class="string">'resize'</span>, () =&gt; &#123;</span><br><span class="line">  debouncedFn(<span class="number">4</span>)</span><br><span class="line">&#125;, <span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 停止缩放1S后输出：</span></span><br><span class="line"><span class="comment">// 原函数的返回值为：16</span></span><br></pre></td></tr></table></figure>

<h3 id="2-使用Promise处理返回值"><a href="#2-使用Promise处理返回值" class="headerlink" title="2. 使用Promise处理返回值"></a>2. 使用Promise处理返回值</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">method, wait, immediate</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> timeout, result</span><br><span class="line">  <span class="keyword">let</span> debounced = <span class="function"><span class="keyword">function</span>(<span class="params">...args</span>) </span>&#123;</span><br><span class="line">    <span class="comment">// 返回一个Promise，以便可以使用then或者Async/Await语法拿到原函数返回值</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="params">resolve</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="keyword">let</span> context = <span class="keyword">this</span></span><br><span class="line">      <span class="keyword">if</span> (timeout) &#123;</span><br><span class="line">        clearTimeout(timeout)</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (immediate) &#123;</span><br><span class="line">        <span class="keyword">let</span> callNow = !timeout</span><br><span class="line">        timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">          timeout = <span class="literal">null</span></span><br><span class="line">        &#125;, wait)</span><br><span class="line">        <span class="keyword">if</span> (callNow) &#123;</span><br><span class="line">          result = method.apply(context, args)</span><br><span class="line">          <span class="comment">// 将原函数的返回值传给resolve</span></span><br><span class="line">          resolve(result)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        timeout = setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">          result = method.apply(context, args)</span><br><span class="line">          <span class="comment">// 将原函数的返回值传给resolve</span></span><br><span class="line">          resolve(result)</span><br><span class="line">        &#125;, wait)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  debounced.cancel = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    clearTimeout(timeout)</span><br><span class="line">    timeout = <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> debounced</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>使用方法一</strong>：在调用防抖后的函数时，使用<code>then</code>拿到原函数的返回值</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">square</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">Math</span>.pow(num, <span class="number">2</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> debouncedFn = debounce(square, <span class="number">1000</span>, <span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">window</span>.addEventListener(<span class="string">'resize'</span>, () =&gt; &#123;</span><br><span class="line">  debouncedFn(<span class="number">4</span>).then(<span class="function"><span class="params">val</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`原函数的返回值为：<span class="subst">$&#123;val&#125;</span>`</span>)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;, <span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 停止缩放1S后输出：</span></span><br><span class="line"><span class="comment">// 原函数的返回值为：16</span></span><br></pre></td></tr></table></figure>

<p><strong>使用方法二</strong>：调用防抖后的函数的外层函数使用Async/Await语法等待执行结果返回</p>
<p>使用方法见代码：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">square</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">Math</span>.pow(num, <span class="number">2</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> debouncedFn = debounce(square, <span class="number">1000</span>, <span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">window</span>.addEventListener(<span class="string">'resize'</span>, <span class="keyword">async</span> () =&gt; &#123;</span><br><span class="line">  <span class="keyword">let</span> val</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    val = <span class="keyword">await</span> debouncedFn(<span class="number">4</span>)</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="built_in">console</span>.error(err)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">`原函数返回值为<span class="subst">$&#123;val&#125;</span>`</span>)</span><br><span class="line">&#125;, <span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 停止缩放1S后输出：</span></span><br><span class="line"><span class="comment">// 原函数的返回值为：16</span></span><br></pre></td></tr></table></figure>
      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/09/06/C++/%E6%B7%B1%E5%85%A5%E6%8E%A2%E7%A9%B6C/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/09/06/C++/%E6%B7%B1%E5%85%A5%E6%8E%A2%E7%A9%B6C/" class="post-title-link" itemprop="url">深入探究C++</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-09-06 20:27:42" itemprop="dateCreated datePublished" datetime="2020-09-06T20:27:42+08:00">2020-09-06</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:18:26" itemprop="dateModified" datetime="2021-11-03T16:18:26+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/C/" itemprop="url" rel="index"><span itemprop="name">C++</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <h1 id="C-的继承与多态"><a href="#C-的继承与多态" class="headerlink" title="C++的继承与多态"></a>C++的继承与多态</h1><h2 id="接口继承与实现继承"><a href="#接口继承与实现继承" class="headerlink" title="接口继承与实现继承"></a>接口继承与实现继承</h2><p>派生类将基类中除去构造函数和析构函数的其他方法继承了过来。public继承概念由两部分组成，函数接口(function interfaces)继承和函数实现(function implementations)继承。作为类的开发人员，我们主要研究类的三种继承情况：<br>1、派生类只继承成员函数的接口(也就是声明)，需要自己来重新定义该函数的实现；<br>2、派生类同时继承函数的接口和实现，但又希望能够覆写(override)它们所继承的实现；<br>3、派生类同时继承函数的接口和实现，并且不允许覆盖任何东西，只能利用父函数的实现；</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Shape</span>&#123;</span><span class="comment">//形状</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">draw</span><span class="params">()</span> <span class="keyword">const</span> </span>= <span class="number">0</span>;</span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">error</span><span class="params">(<span class="keyword">const</span> <span class="built_in">std</span>::<span class="built_in">string</span>&amp; msg)</span></span>;</span><br><span class="line">  <span class="function"><span class="keyword">int</span> <span class="title">objectID</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line">  ...</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Rectangle</span>:</span><span class="keyword">public</span> Shape&#123;...&#125;;<span class="comment">//矩形</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Ellipse</span>:</span><span class="keyword">public</span> Shape&#123;...&#125;;<span class="comment">//椭圆</span></span><br></pre></td></tr></table></figure>

<p>Shape是个抽象类，它的纯虚函数draw使它成为一个抽象类，所以客户不能够创建Shape class的实体，只能创建它的派生类的实体</p>
<p>Shape类声明了三个函数，第一个是draw，在视屏中划出当前对象，第二个是error，准备让那些“需要报导某个错误”的成员函数调用，第三个是objectID，返回当前对象的独一无二的整数识别码，每个函数的声明方式都不相同，draw是个纯虚函数(pure virtual)，error是个虚函数( 简朴的(非纯)impure virtual函数)，objectID是个非虚函数(non-virtual)函数。</p>
<p>纯虚函数通常有两个特点：它们必须被任何“继承了他们”的具象类重新声明；并且它们在抽象类中通常没有定义。<br>所以结论是：声明一个纯虚函数的目的是为了让派生类只继承函数的接口。</p>
<p>虚函数（简朴的impure virtual函数）背后的故事和纯虚函数（pure virtual函数）有点不同，一如往常，派生类继承其函数接口，但虚函数（简朴的impure virtual函数）会提供一份实现代码，派生类可能覆写（override）它，所以结论是：</p>
<p>声明虚函数（简朴的impure virtual函数）的目的是让派生类继承该函数的接口和缺省实现，考虑error函数，其接口表示，每个类都必须支持一个“当遇上错误是可调用”的函数，但每个类可自由处理错误，若某个类不想针对错误做出任何特殊行为，它可以退回到Shape类提供的缺省错误处理行为。但是允许虚函数（简朴的impure virtual函数）同时指定函数声明和函数缺省行为，却有可能造成危险，考虑下面的例子：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//XYZ航空公司的飞机继承体系，该公司只有A型和B型两种飞机，两者都以相同方式飞行，因此XYZ设计的继承体系为：</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Airport</span>&#123;</span>...&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Airplane</span>&#123;</span></span><br><span class="line"><span class="keyword">public</span> :</span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">(<span class="keyword">const</span> Airport&amp; destination)</span></span>;</span><br><span class="line">  ...</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">Airplane::fly</span><span class="params">(<span class="keyword">const</span> Airport&amp; destination)</span></span></span><br><span class="line"><span class="function"></span>&#123;  </span><br><span class="line">  <span class="comment">//缺省代码，将飞机飞至指定的目的地</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ModelA</span>:</span><span class="keyword">public</span> Airplane&#123;...&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ModelB</span>:</span><span class="keyword">public</span> Airplane&#123;...&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//现在，新增加一个C型飞机，C型和A型、B型的飞行方式不同，XYZ公司的程序员在继承体系中针对C型飞机加了一个类，但由于急于让飞机上线，竟然忘了定义其fly函数：</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ModelC</span>:</span><span class="keyword">public</span> Airplane&#123;</span><br><span class="line">    ...  <span class="comment">//为声明fly函数</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>若代码中出现如下操作：<br>Airport PDX(…);//PDX是机场名字<br>Airplane* pa = new ModelC;<br>…<br>pa-&gt;fly(PDX);//调用Airplane::fly</p>
<p>这将酿成大祸，这个程序试图以ModelA或ModelB的飞行方式来飞ModelC。解决该问题的要点在于切断“虚函数接口”和其“缺省实现”之间的连接，下面是一种做法：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Airplane</span>&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">(<span class="keyword">const</span> Airplane&amp; destination)</span> </span>= <span class="number">0</span>;</span><br><span class="line">  ...</span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">defaultFly</span><span class="params">(<span class="keyword">const</span> Airport&amp; destination)</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">Airplane::defaultFly</span><span class="params">(<span class="keyword">const</span> Airport&amp; destination)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"> <span class="comment">// 缺省行为，将飞机飞至指定的目的地</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//现在ModelA和ModelB调用的飞行的缺省实现为：</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ModelA</span>:</span><span class="keyword">public</span> Airplane&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">(<span class="keyword">const</span> Airport&amp; destination)</span></span></span><br><span class="line"><span class="function">  </span>&#123;</span><br><span class="line">    defaultFly(destination);</span><br><span class="line">    ...</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ModelB</span>:</span><span class="keyword">public</span> Airplane&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">(<span class="keyword">const</span> Airport&amp; destination)</span></span></span><br><span class="line"><span class="function">  </span>&#123;</span><br><span class="line">    defaultFly(destination);</span><br><span class="line">    ...</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//现在ModelC class 不可能意外继承不正确的fly实现代码，因为Airplane中的纯虚函数迫使ModelC必须提供自己的fly版本：</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ModelC</span>:</span><span class="keyword">public</span> Airplane&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">fly</span><span class="params">(<span class="keyword">const</span> Airport&amp; destination)</span></span>;</span><br><span class="line">  &#123;</span><br><span class="line">    ...</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">ModelC::fly</span><span class="params">(<span class="keyword">const</span> Airport&amp; destination)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">//将C型飞机飞至指定目的地</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>最后考虑Shape的非虚函数objectID()。若成员函数是个非虚函数，意味着它并不打算在派生类中有不同的行为，实际上非虚成员函数所表现的不变性远重要于特异性，因为它表示不论派生类变得多么特异化，就其自身而言，它的行为都不可以改变。</p>
<p>1、接口继承和实现继承不同。在public继承之下，派生类总是继承基类的接口；</p>
<p>2、纯虚函数只是具体指定接口继承；</p>
<p>3、虚函数( 简朴的（非纯）impure virtual函数)具体指定接口继承及缺省实现继承；</p>
<p>4、非虚函数(non-virtual函数)具体指定接口继承以及强制性实现继承。</p>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>接口继承：派生类只继承函数的接口</p>
<p>实现继承：派生类同时继承函数的接口和实现</p>
<p>虚函数是重载的一种表现方式，是一种动态的重载方式。</p>
<p>非虚函数：继承该函数的接口和一份强制性实现，继承类必须含有某个接口，必须使用基类的实现</p>
<p>虚函数：会继承该函数的接口和缺省实现。继承类必须含有某个接口，可以自己实现，也可以不实现，而采用基类定义的缺省实现。</p>
<p>纯虚函数：纯虚函数在基类中没有定义，接口继承。含有纯虚函数的类无法实例化。要求继承类必须含有某个接口，并对接口函数实现。</p>
<h2 id="多态与继承"><a href="#多态与继承" class="headerlink" title="多态与继承"></a>多态与继承</h2><h3 id="继承访问修饰符"><a href="#继承访问修饰符" class="headerlink" title="继承访问修饰符"></a>继承访问修饰符</h3><p>继承方式有三种——public、protected和private，不同的继承方式对继承到派生类中的基类成员有什么影响？ 总的来说，父类成员的访问限定符通过继承派生到子类中之后，访问限定符的权限小于、等于原权限。其中，父类中的private成员只有父类本身及其友元可以访问，通过其他方式都不能进行访问，当然就包括继承。protected多用于继承当中，如果对父类成员的要求是——子类可访问而外部不可访问，则可以选择protected继承方式。</p>
<h3 id="父子类中同名元素"><a href="#父子类中同名元素" class="headerlink" title="父子类中同名元素"></a>父子类中同名元素</h3><h4 id="overload重载"><a href="#overload重载" class="headerlink" title="overload重载"></a>overload重载</h4><p>函数重载有三个条件，一函数名相同，二形参类型、个数、顺序不同，三相同作用域。根据第三个条件，可知函数重载只可能发生在一个类中</p>
<h4 id="overhide隐藏"><a href="#overhide隐藏" class="headerlink" title="overhide隐藏"></a>overhide隐藏</h4><p>在派生类中将基类中的同名成员方法隐藏，要想在派生类对象中访问基类同名成员得加上基类作用域。(注意，如果该同名方法在基类中实现了重载，在派生类对象中同样需要指定作用域，而不能通过简单的传参，调用带参重载方法)</p>
<h4 id="override函数覆盖"><a href="#override函数覆盖" class="headerlink" title="override函数覆盖"></a>override函数覆盖</h4><p>基类、派生类中的同名方法 函数头相同(参数、返回值)，且基类中该方法为虚函数，则派生类中的同名方法将基类中方法覆盖。函数隐藏和函数覆盖都是发生在基类和派生类之间的，可以这么理解：基类和派生类中的同名函数，除去是覆盖的情况，其他都是隐藏的情况。</p>
<h3 id="引用与指针"><a href="#引用与指针" class="headerlink" title="引用与指针"></a>引用与指针</h3><h4 id="基类对象和派生类对象"><a href="#基类对象和派生类对象" class="headerlink" title=". 基类对象和派生类对象"></a>. 基类对象和派生类对象</h4><p>派生类对象可以赋值给基类对象，基类对象不可以赋值给基类对象；对于基类对象和派生类对象，编译器默认支持从下到上的转换，上是基类，下是派生类。</p>
<h4 id="基类指针-引用-和派生类指针-引用"><a href="#基类指针-引用-和派生类指针-引用" class="headerlink" title="基类指针(引用)和派生类指针(引用)"></a>基类指针(引用)和派生类指针(引用)</h4><p>基类指针(引用)可以指向派生类对象，但只能访问派生类中基类部分的方法，不能访问派生类部分方法。派生类指针(引用)不可以指向基类对象，解引用可能出错，因为派生类的一些方法可能基类没有。</p>
<h3 id="虚函数"><a href="#虚函数" class="headerlink" title="虚函数"></a>虚函数</h3><p>分析：当Base类中有虚函数时，不论是Base类还是Derive类，它们的大小都增加了4个字节。并且当Base<em>指向Derive对象时，</em>Base的类型却变为Derive，不再和指针本身的类型相关，这是怎么回事呢？</p>
<h4 id="虚函数指针"><a href="#虚函数指针" class="headerlink" title="虚函数指针"></a>虚函数指针</h4><p>  实际上，Base和Derive类增加的4个字节就是虚函数指针的大小，每一个类只要有虚函数(包括继承而来的)，它就有且只有一个虚函数指针，类的大小就是总的成员变量的大小加上一个虚函数指针的大小。虚函数指针指向的是一张虚表，里面是这个类所有虚函数的地址，一个类对应一张虚函数表，而虚函数指针存在于每一个对象中，并且永远占据对象内存的前四个字节。</p>
<p>虚函数表又称为“虚表”，它在编译期间就已经确定，在程序运行时就会被装载到只读数据段，在整个程序运行期间都会一直存在。一个类实例化的多个对象，它们 的虚函数指针指向的是同一张虚表。</p>
<h4 id="虚函数要求"><a href="#虚函数要求" class="headerlink" title="虚函数要求"></a>虚函数要求</h4><p>成员函数能实现为虚函数需要满足两个前提条件： 1.成员方法能取地址  2.成员方法依赖于对象。第一点毋庸置疑，虚函数表中需要存储虚函数的地址。第二点，我们怎么调用虚函数的？通过虚函数指针来找到虚表从而调用其中的方法，而虚函数指针又存在于对象中，所以这就意味着虚函数的调用需要依赖对象。</p>
<p>  那么，我们可以确定一些不能实现为虚函数的方法： 1.构造函数——构造函数就是用来创建对象的，如何将其实现为虚函数，使其依赖一个对象调用？ 2.inline函数——内联函数直接在调用点展开，不能取地址 3.static方法——静态方法是属于整个类的，不依赖与单个对象。</p>
<p>成员函数能实现为虚函数需要满足两个前提条件： 1.成员方法能取地址  2.成员方法依赖于对象。第一点毋庸置疑，虚函数表中需要存储虚函数的地址。第二点，我们怎么调用虚函数的？通过虚函数指针来找到虚表从而调用其中的方法，而虚函数指针又存在于对象中，所以这就意味着虚函数的调用需要依赖对象。</p>
<p>  前面我们探讨了那些不能实现虚函数的情况，析构函数是可以的。那么什么时候应该将析构函数实现为虚函数呢？答案是：当基类指针指向堆上开辟的派生类对象时。</p>
<p>静态绑定发生在编译阶段、动态绑定发生在运行阶段。</p>

      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/09/06/%E7%AE%97%E6%B3%95/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%AE%97%E6%B3%95/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/09/06/%E7%AE%97%E6%B3%95/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%AE%97%E6%B3%95/" class="post-title-link" itemprop="url">二叉树算法</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-09-06 16:12:42" itemprop="dateCreated datePublished" datetime="2020-09-06T16:12:42+08:00">2020-09-06</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:30:41" itemprop="dateModified" datetime="2021-11-03T16:30:41+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E7%AE%97%E6%B3%95/" itemprop="url" rel="index"><span itemprop="name">算法</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <h1 id="思路指南"><a href="#思路指南" class="headerlink" title="思路指南"></a>思路指南</h1><h2 id="数据结构的存储方式"><a href="#数据结构的存储方式" class="headerlink" title="数据结构的存储方式"></a>数据结构的存储方式</h2><p>其实只有两种，顺序存储（数组）和链式存储（链表），要有递归的思想，自顶而下，从抽象到具体；</p>
<p>队列、栈：用数组实现，要处理扩容、缩容问题；用链表实现，需要更多内存空间存储节点指针；</p>
<p>图：用二维数组实现，邻接矩阵，判断连通性迅速单图如果稀疏则会耗费时间；链表实现：邻接表，节省空间，但操作效率不够；</p>
<p>散列表：通过散列函数将键映射到一个大数组中，拉链法：链表特性，操作简单但需要额外空间存储指针；线性探查法：数组特性，以便连续寻址，不需要指针存储空间但操作复杂；</p>
<p>树：用数组实现：堆，完全二叉树；链表实现，正常二叉树，二叉搜索树、AVL树、红黑树、区间树、B树；</p>
<h3 id="二者优缺点"><a href="#二者优缺点" class="headerlink" title="二者优缺点"></a>二者优缺点</h3><p>数组：紧凑连续存储，可以随机访问，通过索引快速搜索，相对节省空间，但需要一次分别配够空间，若需要扩容，则重新分配空间并拷贝过去，T(n) = O(n)，且每次进行插入与删除时，必须搬移后面所有数据以保持连续，T(n) = O(N)。</p>
<p>链表：元素不连续，靠指针指向下一个元素的位置，故不存在数组的扩容问题；在知道前驱、后驱时操作指针插入、删除的T(n)=O(1)，但同样因为不连续从而不能根据索引计算对应元素地址，无法随机访问，同样会消耗更多存储空间。</p>
<h3 id="基本操作"><a href="#基本操作" class="headerlink" title="基本操作"></a>基本操作</h3><p>遍历+访问；具体为：增删改查。</p>
<p>线性的，以for/while迭代为代表；</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">traverse</span><span class="params">(<span class="keyword">int</span>[] arr)</span> </span>&#123; </span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; arr.length; i++) &#123; </span><br><span class="line">        <span class="comment">// 迭代访问 arr[i] </span></span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>链表遍历框架，兼具迭代与递归</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 基本的单链表节点 */</span> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ListNode</span> &#123;</span> </span><br><span class="line">    <span class="keyword">int</span> val; </span><br><span class="line">    ListNode next; </span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">traverse</span><span class="params">(ListNode head)</span> </span>&#123; </span><br><span class="line">    <span class="keyword">for</span> (ListNode p = head; p != null; p = p.next) &#123; </span><br><span class="line">        <span class="comment">// 迭代访问 p.val </span></span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">traverse</span><span class="params">(ListNode head)</span> </span>&#123; </span><br><span class="line">    <span class="comment">// 递归访问 head.val </span></span><br><span class="line">    traverse(head.next);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>二叉树遍历框架：典型的非线性递归遍历结构</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 基本的⼆叉树节点 */</span> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TreeNode</span> &#123;</span> </span><br><span class="line">    <span class="keyword">int</span> val; </span><br><span class="line">    TreeNode left, right; </span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">traverse</span><span class="params">(TreeNode root)</span> </span>&#123; </span><br><span class="line">    traverse(root.left); </span><br><span class="line">    traverse(root.right); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>N叉树的遍历：非线性递归</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 基本的 N 叉树节点 */</span> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TreeNode</span> &#123;</span> </span><br><span class="line">    <span class="keyword">int</span> val; </span><br><span class="line">    TreeNode[] children; </span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">traverse</span><span class="params">(TreeNode root)</span> </span>&#123; </span><br><span class="line">    <span class="keyword">for</span> (TreeNode child : root.children) </span><br><span class="line">        traverse(child);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>N叉树的遍历可扩展为图的遍历，如何实现图的环？：用个布尔数组visited做标记。</p>
<p>你就会发现只要涉及递归的问题，都是树的问题；其实很多动态规划问题就是在遍历⼀棵树，你如果对树的遍历操作烂熟于心，起码知道怎么把思路转化成代码，也知道如何提取别⼈解法的核⼼思 路。再看看回溯算法，前⽂回溯算法详解⼲脆直接说了，回溯算法就是个 N 叉 树的前后序遍历问题，没有例外。</p>
<h1 id="medium二叉树刷题（树的核心是递归遍历）"><a href="#medium二叉树刷题（树的核心是递归遍历）" class="headerlink" title="medium二叉树刷题（树的核心是递归遍历）"></a>medium二叉树刷题（树的核心是递归遍历）</h1><h2 id="二叉树中序遍历"><a href="#二叉树中序遍历" class="headerlink" title="二叉树中序遍历"></a>二叉树中序遍历</h2><p>方法一：基于栈的遍历</p>
<p>1、如果left节点存在，就入栈，然后跳left；</p>
<p>2、如果left和right都不存在，则保存当前节点，然后出栈，并让left等于null；</p>
<p>3、如果right存在，且left不存在，则保存当前节点，然后跳right。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Definition for a binary tree node.</span></span><br><span class="line"><span class="comment"> * function TreeNode(val) &#123;</span></span><br><span class="line"><span class="comment"> *     this.val = val;</span></span><br><span class="line"><span class="comment"> *     this.left = this.right = null;</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">&#123;TreeNode&#125;</span> <span class="variable">root</span></span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return <span class="type">&#123;number[]&#125;</span></span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="comment">// 中序遍历</span></span><br><span class="line"><span class="keyword">const</span> inorderTraversal = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">let</span> list = [];</span><br><span class="line">    <span class="keyword">let</span> stack = [];</span><br><span class="line">    <span class="keyword">let</span> node = root;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">while</span>(node || stack.length) &#123;</span><br><span class="line">    <span class="comment">// 遍历左子树</span></span><br><span class="line">      <span class="keyword">while</span>(node) &#123;</span><br><span class="line">          stack.push(node);</span><br><span class="line">          node = node.left;</span><br><span class="line">      &#125;</span><br><span class="line">        node = stack.pop();</span><br><span class="line">        list.push(node.val);</span><br><span class="line">        node = node.right;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> list;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> inorderTraversal = <span class="function"><span class="params">root</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">let</span> res = [], stack = []</span><br><span class="line">  <span class="keyword">while</span> (root || stack.length) &#123;</span><br><span class="line">    <span class="keyword">if</span> (root.left) &#123;</span><br><span class="line">      stack.push(root)；</span><br><span class="line">      root = root.left；</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!root.left &amp;&amp; !root.right) &#123;</span><br><span class="line">      res.push(root.val)；</span><br><span class="line">      root = stack.pop()；</span><br><span class="line">      root &amp;&amp; (root.left = <span class="literal">null</span>)；</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (root.right) &#123;</span><br><span class="line">      res.push(root.val)；</span><br><span class="line">      root = root.right；</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> res</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>方法二：递归</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> inorderTraversal = <span class="function"><span class="keyword">function</span>(<span class="params">root</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> arr = [];</span><br><span class="line">    <span class="keyword">if</span>(!root) <span class="keyword">return</span> [];</span><br><span class="line"></span><br><span class="line">   <span class="keyword">let</span> nums = [root];</span><br><span class="line">    <span class="comment">//递归方法实现</span></span><br><span class="line">    MiddleOrder(root,arr);</span><br><span class="line">    <span class="keyword">return</span> arr;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">MiddleOrder</span>(<span class="params">root,arr</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(root.left)&#123;</span><br><span class="line">        MiddleOrder(root.left,arr);</span><br><span class="line">    &#125;</span><br><span class="line">    arr.push(root.val);</span><br><span class="line">    <span class="keyword">if</span>(root.right)&#123;</span><br><span class="line">        MiddleOrder(root.right,arr);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="前序遍历二叉树"><a href="#前序遍历二叉树" class="headerlink" title="前序遍历二叉树"></a>前序遍历二叉树</h2><p>方法一：基于栈的迭代实现</p>
<p>首先根入栈将根节点出栈，将根节点值放入结果数组中</p>
<p>然后遍历左子树、右子树，因为栈是先入后出，所以，我们先右子树入栈，然后左子树入栈</p>
<p>继续出栈（左子树被出栈）…….</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 前序遍历</span></span><br><span class="line"><span class="keyword">const</span> preorderTraversal = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> list = [];</span><br><span class="line">    <span class="keyword">const</span> stack = [];</span><br><span class="line">    <span class="keyword">let</span> node = root;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">while</span> (node || stack.length)&#123;</span><br><span class="line">        <span class="keyword">while</span> (node)&#123;</span><br><span class="line">            stack.push(node.right);</span><br><span class="line">            list.push(node.val);</span><br><span class="line">            node = node.left;</span><br><span class="line">        &#125;</span><br><span class="line">        node = stack.pop();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> list;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 前序遍历</span></span><br><span class="line"><span class="keyword">var</span> preorderTraversal = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">let</span> result = []</span><br><span class="line">    <span class="keyword">var</span> preOrderTraverseNode = <span class="function">(<span class="params">node</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span>(node) &#123;</span><br><span class="line">            <span class="comment">// 先根节点</span></span><br><span class="line">            result.push(node.val)</span><br><span class="line">            <span class="comment">// 然后遍历左子树</span></span><br><span class="line">            preOrderTraverseNode(node.left)</span><br><span class="line">            <span class="comment">// 再遍历右子树</span></span><br><span class="line">            preOrderTraverseNode(node.right)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    preOrderTraverseNode(root)</span><br><span class="line">    <span class="keyword">return</span> result</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h2 id="后序遍历二叉树"><a href="#后序遍历二叉树" class="headerlink" title="后序遍历二叉树"></a>后序遍历二叉树</h2><p>按照左子树-根-右子树的方式，将其转换成迭代方式。</p>
<p>思路：每到一个节点 A，因为根要最后访问，将其入栈。然后遍历左子树，遍历右子树，最后返回到 A。</p>
<p>但是出现一个问题，无法区分是从左子树返回，还是从右子树返回。</p>
<p>因此，给 A 节点附加一个标记T。在访问其右子树前，T 置为 True。之后子树返回时，当 T 为 True表示从右子树返回，否则从左子树返回。</p>
<p>当 T 为 false 时，表示 A 的左子树遍历完，还要访问右子树。</p>
<p>同时，当 T 为 True 时，表示 A 的两棵子树都遍历过了，要访问 A 了。并且在 A 访问完后，A 这棵子树都访问完成了。</p>
<p>1, 先遍历左节点, 当遍历到末尾节点时, 记录值</p>
<p>2, 然后跳回上一层节点, 顺便让left等于null</p>
<p>3, 再遍历右节点, 同样是遍历到末尾节点时, 记录值</p>
<p>4, 第二次返回时, 让右节点等于null</p>
<p>通过这种人为的方式，不断创造末尾节点值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> postorderTraversal = <span class="function"><span class="params">root</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">let</span> res = [], stack = [];</span><br><span class="line">  <span class="keyword">while</span> (root || stack.length) &#123;</span><br><span class="line">    <span class="keyword">if</span> (root.left) &#123;</span><br><span class="line">      stack.push(root);</span><br><span class="line">      root = root.left;</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (root.right) &#123;</span><br><span class="line">      stack.push(root);</span><br><span class="line">      root = root.right;</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">else</span> &#123;</span><br><span class="line">      res.push(root.val);</span><br><span class="line">      root = stack.pop();</span><br><span class="line">      <span class="keyword">if</span> (root &amp;&amp; root.left) root.left = <span class="literal">null</span>;</span><br><span class="line">      <span class="keyword">else</span> <span class="keyword">if</span> (root &amp;&amp; root.right) root.right = <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="不同的二叉搜索树"><a href="#不同的二叉搜索树" class="headerlink" title="不同的二叉搜索树"></a>不同的二叉搜索树</h2><p>给定一个整数 <em>n</em>，求以 1 … <em>n</em> 为节点组成的二叉搜索树有多少种？</p>
<p>思路：动态规划；为了构建一颗二叉搜索树，可以遍历每一个数字i,将其作为树根，并将1…i-1作为左子树，i+1…n作为右子树，接着可以按照同样方式递归构建左右子树。原问题可以分成规模较小的两个子问题，且解可以复用，因此用动态规划处理。</p>
<p>具体步骤：题目要求是计算不同二叉搜索树的个数。为此，我们可以定义两个函数：G(n): 长度为 n 的序列能构成的不同二叉搜索树的个数。F(i, n): 以 i 为根、序列长度为 n 的不同二叉搜索树个数 (1 \leq i \leq n)(1≤i≤n)。可见，G(n) 是我们求解需要的函数。</p>
<p>动态规划问题的关键在于构建状态转移方程。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> numTrees = <span class="function"><span class="keyword">function</span>(<span class="params">n</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> G = <span class="keyword">new</span> <span class="built_in">Array</span>(n + <span class="number">1</span>).fill(<span class="number">0</span>);</span><br><span class="line">    G[<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line">    G[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">2</span>; i &lt;= n; ++i) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> j = <span class="number">1</span>; j &lt;= i; ++j) &#123;</span><br><span class="line">            G[i] += G[j - <span class="number">1</span>] * G[i - j];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> G[n];</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在本题目的扩展下，如果要求生成所有由1-n节点所组成的二叉搜索树。</p>
<p>和二叉搜索树一的解法不同，一的目的是求数量，而这道题是求具体的解，所以不能从树的规律来简化；利用树的递归特性，采用DFS来递归求解；</p>
<p>n个数组成的二叉树，分为分别以1,2,3…,n为顶点的树；以i为例：f[i]的左边树就是1到i-1个数组成的二叉搜索树，因为左边的节点都比顶点小；f[i]的右边子树就是[i+1]到n的数组成的二叉搜索树，因为右边的节点都比顶点大；左右两侧都是树的数组；组合之后，f[i]的数组组合就得到了。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Definition for a binary tree node.</span></span><br><span class="line"><span class="comment"> * function TreeNode(val, left, right) &#123;</span></span><br><span class="line"><span class="comment"> *     this.val = (val===undefined ? 0 : val)</span></span><br><span class="line"><span class="comment"> *     this.left = (left===undefined ? null : left)</span></span><br><span class="line"><span class="comment"> *     this.right = (right===undefined ? null : right)</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">&#123;number&#125;</span> <span class="variable">n</span></span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return <span class="type">&#123;TreeNode[]&#125;</span></span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> generateTrees = <span class="function"><span class="keyword">function</span> (<span class="params">n</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (n == <span class="number">0</span>) <span class="keyword">return</span> [];</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">getTree</span>(<span class="params">s, e</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (s &gt; e) <span class="keyword">return</span> [<span class="literal">null</span>];</span><br><span class="line">        <span class="keyword">if</span> (s == e) <span class="keyword">return</span> [<span class="keyword">new</span> TreeNode(s)];</span><br><span class="line">        <span class="keyword">var</span> tree = [];</span><br><span class="line">        <span class="keyword">var</span> i = s;</span><br><span class="line">        <span class="keyword">while</span> (i &lt;= e) &#123;</span><br><span class="line">            <span class="keyword">var</span> lefts = getTree(s, i - <span class="number">1</span>), rights = getTree(i + <span class="number">1</span>, e);</span><br><span class="line">            <span class="keyword">while</span> (lefts.length) &#123;</span><br><span class="line">                <span class="keyword">var</span> left = lefts.pop(), j = <span class="number">0</span>;</span><br><span class="line">                <span class="keyword">while</span> (j &lt; rights.length) &#123;</span><br><span class="line">                    <span class="keyword">var</span> right = rights[j];</span><br><span class="line">                    j++;</span><br><span class="line">                    <span class="keyword">var</span> node = <span class="keyword">new</span> TreeNode(i);</span><br><span class="line">                    node.left = left;</span><br><span class="line">                    node.right = right;</span><br><span class="line">                    tree.push(node);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            i++;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> tree;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> getTree(<span class="number">1</span>, n);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>从构建1棵树到构建n棵树，该递归思路其实清晰可见。</p>
<h2 id="验证二叉搜索树"><a href="#验证二叉搜索树" class="headerlink" title="验证二叉搜索树"></a>验证二叉搜索树</h2><p>给定一个二叉树，判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征：1、节点的左子树只包含小于当前节点的数。2、节点的右子树只包含大于当前节点的数。3、所有左子树和右子树自身必须也是二叉搜索树。</p>
<p>方法一：设计一个递归函数来判断，函数表示考虑以root为跟的子树，其子树所有节点是否都在（l,r）的范围内。不在则直接返回，在的话则继续递归调用其左右子树是否满足。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> helper = <span class="function">(<span class="params">root, lower, upper</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="literal">null</span>) <span class="keyword">return</span> ture;</span><br><span class="line">    <span class="keyword">if</span> (root.val &lt;= lower || root.val &gt;= upper) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">return</span> helper(root.left, lower, root.val) &amp;&amp; helper(root.right, root.val, upper);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">var</span> isValidBST = <span class="function"><span class="keyword">function</span>(<span class="params">root</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> helper(root, -<span class="literal">Infinity</span>, <span class="literal">Infinity</span>);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>方法二：中序遍历，二叉搜索树的中序遍历结果一定是升序序列。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> isValidBST = <span class="function"><span class="keyword">function</span>(<span class="params">root</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> stack = [];</span><br><span class="line">    <span class="keyword">let</span> inorder = -<span class="literal">Infinity</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> (stack.length || root !== <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="keyword">while</span> (root !== <span class="literal">null</span>) &#123;</span><br><span class="line">            stack.push(root);</span><br><span class="line">            root = root.left;</span><br><span class="line">        &#125;</span><br><span class="line">        root = stack.pop();</span><br><span class="line">        <span class="comment">// 如果中序遍历得到的节点的值小于等于前一个 inorder，说明不是二叉搜索树</span></span><br><span class="line">        <span class="keyword">if</span> (root.val &lt;= inorder) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        inorder = root.val;</span><br><span class="line">        root = root.right;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h2 id="对称二叉树"><a href="#对称二叉树" class="headerlink" title="对称二叉树"></a>对称二叉树</h2><p>验证一个二叉树是否对称</p>
<p>方法一：递归；左子树和右子树镜像对称则这个树是对称的，1、根节点的值相同；2、一个树的右子树跟另一个树的左子树镜像对称。其实本质跟二叉树相等的递归一样。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> isSymmetric = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> check = <span class="function">(<span class="params">left, right</span>) =&gt;</span> &#123; </span><br><span class="line">    <span class="keyword">if</span> (left == <span class="literal">null</span> &amp;&amp; right == <span class="literal">null</span>) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    <span class="keyword">if</span> (left &amp;&amp; right) &#123;</span><br><span class="line">      <span class="keyword">return</span> left.val == right.val &amp;&amp;</span><br><span class="line">        check(left.left, right.right) &amp;&amp;</span><br><span class="line">        check(left.right, right.left);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (root) &#123;</span><br><span class="line">    <span class="keyword">return</span> check(root.left, root.right);</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>方法二：BFS广度遍历法；入队列的顺序：1、左子树的左子树，右子树的右子树；2、左子树的右子树，右子树的左子树；出队列的时候，检查两两是否对称。</p>
<p>JS中array类型提供了pop()和push()方法来模仿栈这个数据结构的方法；push()方法接受任意数量的参数，并将其逐个添加到数组尾部，并返回修改后数组的长度；pop()方法则从数组末尾溢出最后一项，减少数组的length值，然后返回溢出的项。</p>
<p>而JS用push()和shift()方法结合来模仿队列；shift()方法溢出数组中的第一项并返回该项，同时将数组长度减一；同时也提供了unshift()方法，能在数组前端添加任意项并返回新数组的长度。因此同时使用unshift()和pop()可以从相反方向模拟数列，在前端添加项，从末端移除项。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> isSymmetric = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">if</span> (root == <span class="literal">null</span>) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> leftQueue = [root.left];   <span class="comment">// 队列存放左子树</span></span><br><span class="line">  <span class="keyword">const</span> rightQueue = [root.right]; <span class="comment">// 队列存放右子树</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">while</span> (leftQueue.length &amp;&amp; rightQueue.length) &#123;</span><br><span class="line">    <span class="keyword">const</span> left = leftQueue.shift();</span><br><span class="line">    <span class="keyword">const</span> right = rightQueue.shift();</span><br><span class="line">    <span class="comment">// 左右子树都为空，没有子节点可入列，continue</span></span><br><span class="line">    <span class="keyword">if</span> (left == <span class="literal">null</span> &amp;&amp; right == <span class="literal">null</span>) &#123;</span><br><span class="line">      <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> ((left == <span class="literal">null</span> &amp;&amp; right) || (left &amp;&amp; right == <span class="literal">null</span>)) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (left.val != right.val) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    leftQueue.push(left.left);</span><br><span class="line">    rightQueue.push(right.right);</span><br><span class="line">    leftQueue.push(left.right);</span><br><span class="line">    rightQueue.push(right.left);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 其中一个子树还有节点没遍历，说明不对称</span></span><br><span class="line">  <span class="keyword">if</span> (leftQueue.length || leftQueue.length) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>方法三：利用两个栈来对递归进行模拟</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> isSymmetric = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">if</span> (!root) <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">  <span class="keyword">let</span> leftStack = [], rightStack = [] <span class="comment">// 维护两个栈</span></span><br><span class="line">  <span class="keyword">let</span> curLeft = root.left             <span class="comment">// 当前的左子树</span></span><br><span class="line">  <span class="keyword">let</span> curRight = root.right           <span class="comment">// 当前的右子树</span></span><br><span class="line">  <span class="keyword">while</span> (curLeft || curRight || leftStack.length || rightStack.length) &#123;</span><br><span class="line">    <span class="keyword">while</span> (curLeft) &#123;         <span class="comment">// 左子树存在</span></span><br><span class="line">      leftStack.push(curLeft) <span class="comment">// 推入leftStack栈</span></span><br><span class="line">      curLeft = curLeft.left  <span class="comment">// 不断将左子树入栈</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> (curRight) &#123;          <span class="comment">// 右子树存在</span></span><br><span class="line">      rightStack.push(curRight) <span class="comment">// 推入rightStack栈</span></span><br><span class="line">      curRight = curRight.right <span class="comment">// 不断将右子树压入栈</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (leftStack.length !== rightStack.length) <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">                                <span class="comment">// 栈的高度不相等，说明结构不对称</span></span><br><span class="line">    curLeft = leftStack.pop()   <span class="comment">// 栈顶节点出栈，赋给curLeft</span></span><br><span class="line">    curRight = rightStack.pop() <span class="comment">// 栈顶节点出栈，赋给curRight</span></span><br><span class="line">    <span class="keyword">if</span> (curLeft.val !== curRight.val) <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">                                <span class="comment">// 两个栈出栈的节点值不相等 不对称</span></span><br><span class="line">    curLeft = curLeft.right     <span class="comment">// 考察左子树的right</span></span><br><span class="line">    curRight = curRight.left    <span class="comment">// 考察右子树的left</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="二叉树的BFS与DFS"><a href="#二叉树的BFS与DFS" class="headerlink" title="二叉树的BFS与DFS"></a>二叉树的BFS与DFS</h2><p>DFS：深度优先搜索一般使用递归的方法进行实现。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> dfs = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="literal">null</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> ;</span><br><span class="line">    &#125;</span><br><span class="line">    dfs(root.left);</span><br><span class="line">    dfs(root.right);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>BFS则是使用队列的数据结构来进行遍历；</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> dfs = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">var</span> queue = [];</span><br><span class="line">    queue.push(root);</span><br><span class="line">    <span class="keyword">while</span> (queue.length != <span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">var</span> node = queue.shift();</span><br><span class="line">        <span class="keyword">if</span> (node.left != <span class="literal">null</span>)&#123;</span><br><span class="line">            queue.push(node.left);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (node.right != <span class="literal">null</span>)&#123;</span><br><span class="line">            queue.push(node.right);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>递归的方法其实隐含地使用了系统的栈，不需要自己去维护数据结构；BFS这种独特的遍历方式正式其用于求解层序遍历和最短路径问题的根本原因。</p>
<h2 id="层序遍历与最小路径问题"><a href="#层序遍历与最小路径问题" class="headerlink" title="层序遍历与最小路径问题"></a>层序遍历与最小路径问题</h2><p>1、层序遍历；利用BFS遍历二叉树无法区分队列中的节点来自哪一层，因此需要修改下代码记录队列中节点数量n（即这一层的节点数），然后一口气处理该层n个节点。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> dfs = <span class="function">(<span class="params">root</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">var</span> queue = [], res = [], level = [];</span><br><span class="line">    queue.push(root);</span><br><span class="line">    <span class="keyword">while</span> (queue.length != <span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">var</span> n = queue.length;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; n; i++)&#123;</span><br><span class="line">        	<span class="keyword">var</span> node = queue.shift();</span><br><span class="line">            level.push(node.val);</span><br><span class="line">        	<span class="keyword">if</span> (node.left != <span class="literal">null</span>)&#123;</span><br><span class="line">            	queue.push(node.left);</span><br><span class="line">        	&#125;</span><br><span class="line">        	<span class="keyword">if</span> (node.right != <span class="literal">null</span>)&#123;</span><br><span class="line">            	queue.push(node.right);</span><br><span class="line">        	&#125;</span><br><span class="line">        &#125;</span><br><span class="line">        res.pop(level);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其实根据上述层序遍历的代码，要实现二叉树层序遍历的反向输出，只需要修改最后res的入队列方式即可，用unshift来代替pop。</p>
<p>2、最短路径问题：在树中一个节点到一个节点的路径是唯一的，但在图中可能有多条路径，找寻哪一条路径最短。在BFS中，距离源点越近的点会先被遍历到。（Dijkstra算法解决的是带权最短路径问题，而BFS解决的是无权最短路径问题）</p>
<h2 id="二叉树的锯齿形层次遍历"><a href="#二叉树的锯齿形层次遍历" class="headerlink" title="二叉树的锯齿形层次遍历"></a>二叉树的锯齿形层次遍历</h2><p>给定一个二叉树，返回其节点值的锯齿形层次遍历。（即先从左往右，再从右往左进行下一层遍历，以此类推，层与层之间交替进行）</p>
<p>思路：典型广度优先题目；广度优先通过队列处理 【深度优先用栈】</p>
<p>1、将一层记录在数组中 并记录数组长度找下一行所有数据将数组首位弹出 将首位的左右节点追在数组后；</p>
<p>2、按照记录的数组长度 将上层的结点全部弹出后 此时数组只剩下下一行结点了 此时就完成了一层的遍历；类似上题 与上题区别 每层输出反向 加个条件即可</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">* @<span class="keyword">return</span> &#123;number[][]&#125;</span><br><span class="line"> *</span><br><span class="line"><span class="keyword">var</span> zigzagLevelOrder = <span class="function"><span class="keyword">function</span>(<span class="params">root</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">if</span>(root==<span class="literal">null</span>)</span><br><span class="line">    <span class="keyword">return</span> []</span><br><span class="line">  <span class="keyword">var</span> arr=[root]</span><br><span class="line">  <span class="keyword">var</span> res=[]</span><br><span class="line">  <span class="keyword">var</span> go=<span class="literal">true</span></span><br><span class="line">  <span class="keyword">while</span>(arr.length&gt;<span class="number">0</span>)&#123;</span><br><span class="line">    <span class="keyword">var</span> n=arr.length</span><br><span class="line">    <span class="keyword">var</span> now=[]</span><br><span class="line">    <span class="keyword">if</span>(go)&#123;</span><br><span class="line">      <span class="keyword">while</span>(n--&gt;<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">var</span> node=arr.shift()</span><br><span class="line">        now.push(node.val)</span><br><span class="line">        <span class="keyword">if</span>(node.left!=<span class="literal">null</span>)arr.push(node.left)</span><br><span class="line">        <span class="keyword">if</span>(node.right!=<span class="literal">null</span>)arr.push(node.right)</span><br><span class="line">      &#125;</span><br><span class="line">      res.push(now)</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">      <span class="keyword">while</span>(n--&gt;<span class="number">0</span>)&#123;</span><br><span class="line">        <span class="keyword">var</span> node=arr.pop()</span><br><span class="line">        now.push(node.val)</span><br><span class="line">        <span class="keyword">if</span>(node.right!=<span class="literal">null</span>)arr.unshift(node.right)</span><br><span class="line">        <span class="keyword">if</span>(node.left!=<span class="literal">null</span>)arr.unshift(node.left)</span><br><span class="line">      &#125;</span><br><span class="line">      res.push(now)</span><br><span class="line">    &#125;</span><br><span class="line">    go=!go</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> res</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>





<h2 id="前序跟中序遍历构造二叉树"><a href="#前序跟中序遍历构造二叉树" class="headerlink" title="前序跟中序遍历构造二叉树"></a>前序跟中序遍历构造二叉树</h2><p>思路：构建一个二叉树需要构建三部分：root、左子树、右子树；左子树、右子树的构建，又包括：root、左子树、右子树解题关键在于定位出根节点，划分出左右子树，然后 递归 构建左右子树</p>
<p>具体做法：preorder 数组的第一项肯定是根节点 —— 因为前序遍历的顺序是 [根| 左|右 ][根∣左∣右]。由根节点，在 inorder [左 | 根 | 右][左∣根∣右] 中划分出左、右子树的 inorder 序列。<br>通过 inorder 中左右子树的节点个数，在 preorder 中确定左、右子树的 preorder 序列。得到左、右子树的 preorder 和 inorder 序列，就能递归构建左右子树。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> buildTree = <span class="function">(<span class="params">preorder, inorder</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">if</span> (inorder.length == <span class="number">0</span>) <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">  <span class="keyword">const</span> root = <span class="keyword">new</span> TreeNode(preorder[<span class="number">0</span>]);</span><br><span class="line">  <span class="keyword">const</span> mid = inorder.indexOf(preorder[<span class="number">0</span>]);</span><br><span class="line">  root.left = buildTree(preorder.slice(<span class="number">1</span>, mid + <span class="number">1</span>), inorder.slice(<span class="number">0</span>, mid));</span><br><span class="line">  root.right = buildTree(preorder.slice(mid + <span class="number">1</span>), inorder.slice(mid + <span class="number">1</span>));</span><br><span class="line">  <span class="keyword">return</span> root;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>优化一:字符串截取性能消耗比较大，没必要每次均将preorder、inorder切割；用两个指针表示即可，写一个接受指针的辅助函数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> buildTree = <span class="function">(<span class="params">preorder, inorder</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> helper = <span class="function">(<span class="params">p_start, p_end, i_start, i_end</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (p_start &gt; p_end) <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">let</span> rootVal = preorder[p_start];    <span class="comment">// 根节点的值</span></span><br><span class="line">    <span class="keyword">let</span> root = <span class="keyword">new</span> TreeNode(rootVal);   <span class="comment">// 根节点</span></span><br><span class="line">    <span class="keyword">let</span> mid = inorder.indexOf(rootVal); <span class="comment">// 根节点在inorder的位置</span></span><br><span class="line">    <span class="keyword">let</span> leftNum = mid - i_start;        <span class="comment">// 左子树的节点数</span></span><br><span class="line">    root.left = helper(p_start + <span class="number">1</span>, p_start + leftNum, i_start, mid - <span class="number">1</span>);</span><br><span class="line">    root.right = helper(p_start + leftNum + <span class="number">1</span>, p_end, mid + <span class="number">1</span>, i_end);</span><br><span class="line">    <span class="keyword">return</span> root;</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="keyword">return</span> helper(<span class="number">0</span>, preorder.length - <span class="number">1</span>, <span class="number">0</span>, inorder.length - <span class="number">1</span>);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>再次优化：每次递归都要indexof寻找根节点位置，耗费性能；可提前把inorder数组元素和索引存到hash表中。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> buildTree = <span class="function">(<span class="params">preorder, inorder</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> map = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; inorder.length; i++) &#123;</span><br><span class="line">    map.set(inorder[i], i);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">const</span> helper = <span class="function">(<span class="params">p_start, p_end, i_start, i_end</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (p_start &gt; p_end) <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">let</span> rootVal = preorder[p_start];    <span class="comment">// 根节点的值</span></span><br><span class="line">    <span class="keyword">let</span> root = <span class="keyword">new</span> TreeNode(rootVal);   <span class="comment">// 根节点</span></span><br><span class="line">    <span class="keyword">let</span> mid = map.get(rootVal);         <span class="comment">// 根节点在inorder的位置</span></span><br><span class="line">    <span class="keyword">let</span> leftNum = mid - i_start;        <span class="comment">// 左子树的节点数</span></span><br><span class="line">    root.left = helper(p_start + <span class="number">1</span>, p_start + leftNum, i_start, mid - <span class="number">1</span>);</span><br><span class="line">    root.right = helper(p_start + leftNum + <span class="number">1</span>, p_end, mid + <span class="number">1</span>, i_end);</span><br><span class="line">    <span class="keyword">return</span> root;</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="keyword">return</span> helper(<span class="number">0</span>, preorder.length - <span class="number">1</span>, <span class="number">0</span>, inorder.length - <span class="number">1</span>);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h2 id="中序跟后序遍历构造二叉树"><a href="#中序跟后序遍历构造二叉树" class="headerlink" title="中序跟后序遍历构造二叉树"></a>中序跟后序遍历构造二叉树</h2><p>通常从先序序列或者后序序列开始，根据不同遍历方法的规律，选择合适的节点构造树。例如：先序序列的 第一个 节点是根节点，然后是它的左孩子，右孩子等等。后序序列的 最后一个 节点是根节点，然后是它的右孩子，左孩子等等。</p>
<p>从先序/后序序列中找到根节点，根据根节点将中序序列分为左子树和右子树。从中序序列中获得的信息是：如果当前子树为空（返回 None），否则继续构造子树。</p>
<p>创建 hashmap 存储中序序列：value -&gt; its index 。</p>
<p>方法 helper 的参数是中序序列中当前子树的左右边界，该方法仅用于检查子树是否为空。下面分析 helper(in_left = 0, in_right = n - 1) 的逻辑：</p>
<p>1、如果 in_left &gt; in_right，说明子树为空，返回 None。</p>
<p>2、选择后序遍历的最后一个节点作为根节点。</p>
<p>3、假设根节点在中序遍历中索引为 index。从 in_left 到 index - 1 属于左子树，从 index + 1 到 in_right 属于右子树。</p>
<p>4、根据后序遍历逻辑，递归创建右子树 helper(index + 1, in_right) 和左子树 helper(in_left, index - 1)。</p>
<p>5、返回根节点 root</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> buildTree = <span class="function"><span class="keyword">function</span>(<span class="params">inorder, postorder</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> p = i = postorder.length - <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">let</span> build = <span class="function">(<span class="params">stop</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span>(inorder[i] != stop) &#123;</span><br><span class="line">            <span class="keyword">let</span> root = <span class="keyword">new</span> TreeNode(postorder[p--])</span><br><span class="line">            root.right = build(root.val)</span><br><span class="line">            i--</span><br><span class="line">            root.left = build(stop)</span><br><span class="line">            <span class="keyword">return</span> root</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> build()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="翻转二叉树"><a href="#翻转二叉树" class="headerlink" title="翻转二叉树"></a>翻转二叉树</h2><p>递归三步法：1、确定递归函数的参数和返回值；2、确定终止条件；3、确定单层递归的逻辑。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Definition for a binary tree node.</span></span><br><span class="line"><span class="comment"> * function TreeNode(val) &#123;</span></span><br><span class="line"><span class="comment"> *     this.val = val;</span></span><br><span class="line"><span class="comment"> *     this.left = this.right = null;</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">&#123;TreeNode&#125;</span> <span class="variable">root</span></span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return <span class="type">&#123;TreeNode&#125;</span></span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> invertTree = <span class="function"><span class="keyword">function</span>(<span class="params">root</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="literal">null</span>) <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">const</span> left = invertTree(root.left);</span><br><span class="line">    <span class="keyword">const</span> right = invertTree(root.right);</span><br><span class="line">    root.left = right;</span><br><span class="line">    root.right = left;</span><br><span class="line">    <span class="keyword">return</span> root;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h2 id="将有序数组转换为二叉搜索树"><a href="#将有序数组转换为二叉搜索树" class="headerlink" title="将有序数组转换为二叉搜索树"></a>将有序数组转换为二叉搜索树</h2><p>该解题的本质不在于二叉搜索树和中序遍历，本质是平衡。</p>
<p>如何满足平衡条件：每次把一组数最中间的位置作为树的头拎起来，剩余的部分平均分两份，剩余的一个随便给左子树或右子树；</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">def 做一棵树（数组的哪个段落要做成树）：#这个段落用索引表示即可，与具体数字无关</span><br><span class="line">    #假设这个段落叫A吧</span><br><span class="line">    树的根部 &#x3D; 这个段落A最中间的数字</span><br><span class="line">    树的左边 &#x3D; 做一棵树（这个段落A的左边部分）</span><br><span class="line">    树的右边 &#x3D; 做一棵树（这个段落A的右边部分）</span><br><span class="line">    return 这棵树</span><br></pre></td></tr></table></figure>

<p>二叉搜索树中序遍历后正好是一个递增的数组；因此，其实这个树就是我们中序遍历二叉树的结果。因此我们以和中序遍历相反的方式，从中间开始取root进行构建二叉树即可。</p>
<p>#可以看到整个题解只和index有关，和数组里的具体数字无关，        #因为题目给出的“有序数列”帮助我们满足了“二叉搜索树”的条件。因此只需要操作index来对节点进行重新构建即可。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sortedArrayToBST = <span class="function">(<span class="params">nums</span>) =&gt;</span> &#123;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> buildBST = <span class="function">(<span class="params">nums, start, end</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (start &gt; end) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="comment">//无符号右移&gt;&gt;&gt;的操作是：丢弃右边指定位数，并左边补上0，因此等于除以2。</span></span><br><span class="line">    <span class="keyword">const</span> mid = (start + end) &gt;&gt;&gt; <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">const</span> root = <span class="keyword">new</span> TreeNode(nums[mid]);</span><br><span class="line"></span><br><span class="line">    root.left = buildBST(nums, start, mid - <span class="number">1</span>);</span><br><span class="line">    root.right = buildBST(nums, mid + <span class="number">1</span>, end);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> root;</span><br><span class="line">  &#125;;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">return</span> buildBST(nums, <span class="number">0</span>, nums.length - <span class="number">1</span>);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

























<h1 id="二叉树hard题目"><a href="#二叉树hard题目" class="headerlink" title="二叉树hard题目"></a>二叉树hard题目</h1><h2 id="恢复二叉搜索树"><a href="#恢复二叉搜索树" class="headerlink" title="恢复二叉搜索树"></a>恢复二叉搜索树</h2><p>二叉搜索树中的两个节点被错误地交换。</p>
<p>请在不改变其结构的情况下，恢复这棵树。</p>
<p>找到二叉搜索树中序遍历得到值序列的不满足条件的位置。本方法开辟一个新数组 \textit{nums}nums 来记录中序遍历得到的值序列，然后线性遍历找到两个位置 i和 j，并重新遍历原二叉搜索树修改对应节点的值完成修复，</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> inorder = <span class="function">(<span class="params">root, nums</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (root === <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    inorder(root.left, nums);</span><br><span class="line">    nums.push(root.val);</span><br><span class="line">    inorder(root.right, nums);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> findTwoSwapped = <span class="function">(<span class="params">nums</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> n = nums.length;</span><br><span class="line">    <span class="keyword">let</span> x = <span class="number">-1</span>, y = <span class="number">-1</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; n - <span class="number">1</span>; ++i) &#123;</span><br><span class="line">        <span class="keyword">if</span> (nums[i + <span class="number">1</span>] &lt; nums[i]) &#123;</span><br><span class="line">            y = nums[i + <span class="number">1</span>];</span><br><span class="line">            <span class="keyword">if</span> (x === <span class="number">-1</span>) &#123;</span><br><span class="line">                x = nums[i];</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> [x, y];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> recover = <span class="function">(<span class="params">r, count, x, y</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (r !== <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (r.val === x || r.val === y) &#123;</span><br><span class="line">            r.val = r.val === x ? y : x;</span><br><span class="line">            <span class="keyword">if</span> (--count === <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        recover(r.left, count, x, y);</span><br><span class="line">        recover(r.right, count, x, y);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> recoverTree = <span class="function"><span class="keyword">function</span>(<span class="params">root</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> nums = [];</span><br><span class="line">    inorder(root, nums);</span><br><span class="line">    <span class="keyword">const</span> [first, second] = findTwoSwapped(nums);</span><br><span class="line">    recover(root, <span class="number">2</span>, first, second); </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>


      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/09/04/%E5%89%8D%E7%AB%AF/JavaScript%E7%BC%96%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/09/04/%E5%89%8D%E7%AB%AF/JavaScript%E7%BC%96%E7%A8%8B/" class="post-title-link" itemprop="url">JavaScript编程</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-09-04 18:55:49" itemprop="dateCreated datePublished" datetime="2020-09-04T18:55:49+08:00">2020-09-04</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:25:37" itemprop="dateModified" datetime="2021-11-03T16:25:37+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E5%89%8D%E7%AB%AF%E9%A1%B5%E9%9D%A2/" itemprop="url" rel="index"><span itemprop="name">前端页面</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <p>HTML定义了网页的内容；CSS 描述了网页的布局；JavaScript确定了网页的行为。</p>
<p>一个完成的JS实现由下面三部分组成：1、核心ECMAScript；2、文档对象模型DOM；2、浏览器对象模型BOM。</p>
<p>1、ECMAScript与Web浏览器没有依赖关系，就是对实现该标准规定的各方面内容的语言的描述；</p>
<p>2、文档对象模型DOM：针对XML但经过扩展用于HTML的应用程序编程接口API；DOM把整个页面映射为一个多层节点结构，HTML页面中每个组成部分都是某种类型的节点，这些节点又包含着不同类型的数据；通过DOM创建的这个表示文档的树形图，开发者获得了控制页面内容和结构的主动权。借助DOM提供的API，开发人员可以自如地删除、添加、替换或修改任何节点。</p>
<p>3、浏览器对象模型BOM：开发人员使用BOM控制浏览器显示的界面以外的部分，</p>
<p>1、使用script元素嵌入JavaScript代码时，只须为script指定type属性，type=”text/javascript”，之后将JS代码直接放在元素内部，且包含在script内部的JS代码将从上至下被解释；即在解释器对script页面内的所有代码求值完以前，页面中其余内容都不会被浏览器加载或显示。</p>
<p>2、如果要通过script元素来包含外部JS文件，那么需要SRC属性，是一个指向外部JS文件的链接；</p>
<p>且带有src属性的script元素不应该在其script和/script标签之间再包含额外的JS代码，如果包含则只会下载并执行外部脚本文件而忽略内部嵌入的代码。</p>
<p>甚至SRC属性可以包含外部域的JS</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"example.js"</span> /&gt;</span></span><br><span class="line"><span class="handlebars"><span class="xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"http://www.somewhere.com/afile.js"</span>&gt;</span></span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>现代WEB应用一般把全部JS引用放在body元素中页面内容的后面，以免加载时间过长；或者加上defer作为延迟脚本（延迟至html页面加载完毕），加上async作为异步脚本（不让页面等待两个脚本下载、执行，从而异步加载其他内容）。</p>
<p>一般还是尽可能得用外部文件来包含JS代码，可维护性、可缓存、适应未来。</p>
<h2 id="1、基本概念"><a href="#1、基本概念" class="headerlink" title="1、基本概念"></a>1、基本概念</h2><h4 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h4><p>松散类型变量，定义时用var后跟变量名，该变量可以用于保存任何值；但用var操作符定义的变量将成为定义该变量作用域中得局部变量，如果在函数中定义，则函数退出后便会销毁该变量。省略var操作符时可定义全局变量，但及其不推荐。</p>
<h4 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h4><p>5种简单得：Undefined（未定义）、Null（空）、Boolean（布尔型）、Number（数值）、String（字符串）；还有一种复杂的：Object（对象），数据类型具有动态性，无需再定义。用typeof操作符来返回给定变量的数据类型。</p>
<p>Undefined：只有一个值undefined，使用var声明变量时未对其初始化；</p>
<p>Null：只有一个值null，逻辑上表示一个空对象指针，因此使用typeof检测null值时会返回object，定义的变量要存储值则先初始化为null，可直接检查该值判断是否已经保存了一个对象的引用。事实上，undefined值派生自null值，因此它们的相等性测试返回true。</p>
<p>Boolean类型：只有两个字面值：true、false，且区分大小写，即True和False不是布尔类型，只是标识符，调用转型函数Boolean（）可以转换成对应的布尔值。</p>
<p>Number类型：表示整型和浮点数值，十进制、八进制（字面值第一位为0）、十六进制（字面值第一位为0X），ECMAScript会适时地自动将浮点型变为整型，对于极大、极小的数可用e来表示法表示的浮点数值表示。数值范围：Number.MIN_VALUE到Number.MAX_VALUE。</p>
<p>NaN：非数值，是一个特殊的数值，用于表示一个本来要返回数值的操作数未返回数值的情况。任何涉及NaN的操作都会返回NaN，因此用isNaN()函数，不能转换成数值的值都会导致该函数返回true，字符串”blue“不能转换成数值，因此返回true。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> floatNum = <span class="number">3.125e7</span></span><br><span class="line"><span class="comment">//e表示法表示的数值等于e前面的数乘以10的指数次幂</span></span><br></pre></td></tr></table></figure>

<p>Number():用于任何数据类型转换成数值；parseInt()：处理整数；parseFloat()：处理浮点数字字符。</p>
<p>String类型：单、双引号没有区别，包含一些转义序列；ECMAScript中字符串不可变，要改变一个字符串，首先要销毁原来的字符串，再用一个包含新值得字符串填充该变量。</p>
<p>toString()方法，返回对应值字符串；String()转型函数。</p>
<p>object类型：对象其实就是一组数据和功能的集合，对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。Object的每个实例都具有下列方法、属性：</p>
<p>constructor:保存着用于创建当前对象的函数，构造函数；</p>
<p>hasOwnProperty(propertyName)：用于检查给定的属性在当前对象实例中是否存在，其中作为参数的属性名propertyName必须以字符串的形式指定；</p>
<p>isPrototypeOf(object)：用于检查传入的对象是否是当前对象的原型；</p>
<p>propertyIsEnumerable(propertyName)：用于检查给定的属性是否能够使用for-in语句来枚举，与hasOwnProperty(propertyName)方法一样，作为参数的属性名必须以字符串形式指定；</p>
<p>toLocaleString()：返回对象的字符串表示，该字符串与执行环境的地区对应；</p>
<p>toString()：返回对象的字符串表示；</p>
<p>valueOf()：返回对象的字符串、数值或布尔值表示。</p>
<h4 id="操作符"><a href="#操作符" class="headerlink" title="操作符"></a>操作符</h4><p>一元加操作符：对非数值应用时，该操作符会像Number转型函数一样对这个值执行转换；一元减操作符主要用于表示负数；</p>
<p>位操作符：用于最基本的层次上，即按内存中表示数值的位来操作数据，按位非~；按位与&amp;；按位或 | ;按位异或 ^；左移 &lt;&lt;;有符号的</p>

      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/09/02/%E5%89%8D%E7%AB%AF/CSS%E6%A0%B7%E5%BC%8F%E8%A1%A8%E7%BC%96%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/09/02/%E5%89%8D%E7%AB%AF/CSS%E6%A0%B7%E5%BC%8F%E8%A1%A8%E7%BC%96%E7%A8%8B/" class="post-title-link" itemprop="url">CSS样式表编程</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-09-02 21:58:38" itemprop="dateCreated datePublished" datetime="2020-09-02T21:58:38+08:00">2020-09-02</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:25:17" itemprop="dateModified" datetime="2021-11-03T16:25:17+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E5%89%8D%E7%AB%AF%E9%A1%B5%E9%9D%A2/" itemprop="url" rel="index"><span itemprop="name">前端页面</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <h2 id="1、CSS语法"><a href="#1、CSS语法" class="headerlink" title="1、CSS语法"></a>1、CSS语法</h2><p>两个主要部分：选择器 + 一条或者多条声明；每条声明由一个属性和一个值组成，属性是希望设置的样式属性，每个属性有一个值。CSS声明总是以分号结束，声明总以大括号括起来。</p>
<p>如果要在HTML元素中设置CSS样式，需要在元素中设置id、class选择器。</p>
<p>id选择器可以为标有特定id的HTML元素指定特定的样式，HTML元素以id属性来设置id选择器，CSS中id选择器以#来定义。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-id">#para1</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">text-align</span><span class="selector-pseudo">:center</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">color</span><span class="selector-pseudo">:red</span>;</span></span><br><span class="line">&#125; </span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">id</span>=<span class="string">"para1"</span>&gt;</span>Hello World!<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>这个段落不受该样式的影响。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>class选择器用于描述一组元素的样式，区别在于class可以在多个元素中使用，</p>
<h3 id="插入CSS"><a href="#插入CSS" class="headerlink" title="插入CSS"></a>插入CSS</h3><p>外部样式表：改变一个文件来改变一个站点的外观；每个页面使用 link标签链接到样式表。link标签在文档的头部：而浏览器会从文件mystyle.css中读到样式，并根据它来格式文档。外部样式表可在任何文本编辑器进行编辑，不能包含任何html标签，应该以CSS的扩展名进行保存，</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">hr</span> &#123;<span class="attribute">color</span>:sienna;&#125;</span><br><span class="line"><span class="selector-tag">p</span> &#123;<span class="attribute">margin-left</span>:<span class="number">20px</span>;&#125;</span><br><span class="line"><span class="selector-tag">body</span> &#123;<span class="attribute">background-image</span>:<span class="built_in">url</span>(<span class="string">"/images/back40.gif"</span>);&#125;</span><br></pre></td></tr></table></figure>

<p>内部样式表：当单个文档需要特殊格式时，可以使用，可用style标签在文档头部定义内部样式表。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-tag">hr</span> &#123;<span class="attribute">color</span>:sienna;&#125;</span></span><br><span class="line"><span class="css"><span class="selector-tag">p</span> &#123;<span class="attribute">margin-left</span>:<span class="number">20px</span>;&#125;</span></span><br><span class="line"><span class="css"><span class="selector-tag">body</span> &#123;<span class="attribute">background-image</span>:<span class="built_in">url</span>(<span class="string">"images/back40.gif"</span>);&#125;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>内联样式：</p>
<p>多重样式：某些属性在不同样式表中被同样的选择器定义，那么属性值将从更具体的样式表中被继承过来。</p>
<p>多重样式优先级：可以在同一个HTML文档内部引用多个外部样式表。优先级如下：内联样式&gt;内部样式&gt;外部样式&gt;浏览器默认样式</p>
<h3 id="CSS背景"><a href="#CSS背景" class="headerlink" title="CSS背景"></a>CSS背景</h3><p>背景属性用于定义HTML元素的背景：</p>
<p>background-color：背景颜色；background-image：背景图像；background-repeat:设置背景不平铺；background-position:背景定位；</p>
<h3 id="CSS文本格式"><a href="#CSS文本格式" class="headerlink" title="CSS文本格式"></a>CSS文本格式</h3><p>格式：颜色color、对齐方式text-align、文本修饰text-decoration、文本大小写转换text-transform、文本缩进text-indent。</p>
<p>字体：两种类型的字体系列名称，通用字体、特定字体。font-family属性设置文本的字体系列，</p>
<h3 id="CSS链接"><a href="#CSS链接" class="headerlink" title="CSS链接"></a>CSS链接</h3><p>四个基本的链接样式实例：</p>
<p>a:link - 正常，未访问过的链接</p>
<p>a:visited - 用户已访问过的链接</p>
<p>a:hover - 当用户鼠标放在链接上时</p>
<p>a:active - 链接被点击的那一刻</p>
<h3 id="CSS盒子模型"><a href="#CSS盒子模型" class="headerlink" title="CSS盒子模型"></a>CSS盒子模型</h3><p>所有HTML元素可以看作盒子，在CSS中，box model这一术语是用来设计和布局时使用的，CSS盒模型本质上是一个盒子，封装周围的HTML元素，包括：边框、边距、填充、实际内容。盒模型允许我们在其他元素和周围元素边框之间的空间放置元素。</p>
<p>不同部分的说明：</p>
<p>outline轮廓：绘制于元素周围的一条线，位于边框边缘的外围，起突出元素的作用。</p>
<p>Margin(外边距)** - 清除边框外的区域，外边距是透明的。可以单独改变元素四周边框，也可以一次改变所有属性。</p>
<p>Border(边框)** - 围绕在内边距和内容外的边框，允许一个元素边框的样式和颜色。</p>
<p>Padding(内边距)** - 清除内容周围的区域，内边距是透明的。</p>
<p>Content(内容)** - 盒子的内容，显示文本和图像</p>
<h3 id="CSS分组与嵌套"><a href="#CSS分组与嵌套" class="headerlink" title="CSS分组与嵌套"></a>CSS分组与嵌套</h3><p>分组选择器：在样式表中有很多具有相同样式的元素，可使用分组选择器，每个选择器用逗号分隔。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line">h1,h2,p</span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">color</span><span class="selector-pseudo">:green</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Hello World!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>Smaller heading!<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>This is a paragraph.<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>嵌套选择器：适用于选择器内部的选择器样式，</p>
<ul>
<li><strong>p{ }</strong>: 为所有 <strong>p</strong> 元素指定一个样式。</li>
<li><strong>.marked{ }</strong>: 为所有 <strong>class=”marked”</strong> 的元素指定一个样式。</li>
<li><strong>.marked p{ }</strong>: 为所有 <strong>class=”marked”</strong> 元素内的 <strong>p</strong> 元素指定一个样式。</li>
<li><strong>p.marked{ }</strong>: 为所有 <strong>class=”marked”</strong> 的 <strong>p</strong> 元素指定一个样式</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line">p</span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">color</span><span class="selector-pseudo">:blue</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">text-align</span><span class="selector-pseudo">:center</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="css"><span class="selector-class">.marked</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">background-color</span><span class="selector-pseudo">:red</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="css"><span class="selector-class">.marked</span> <span class="selector-tag">p</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">color</span><span class="selector-pseudo">:white</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="css"><span class="selector-tag">p</span><span class="selector-class">.marked</span>&#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">text-decoration</span><span class="selector-pseudo">:underline</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>这个段落是蓝色文本，居中对齐。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"marked"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>这个段落不是蓝色文本。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>所有 class="marked"元素内的 p 元素指定一个样式，但有不同的文本颜色。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">	</span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"marked"</span>&gt;</span>带下划线的 p 段落。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><img src="/../../image/CSS%E6%A0%B7%E5%BC%8F%E8%A1%A8%E7%BC%96%E7%A8%8B/CSS%E5%B5%8C%E5%A5%97.png" alt="CSS嵌套"></p>
<h3 id="CSS显示与定位"><a href="#CSS显示与定位" class="headerlink" title="CSS显示与定位"></a>CSS显示与定位</h3><p>display元素设置一个元素应如何显示，visibility属性指定一个元素可见还是隐藏。</p>
<p>visibility：hidden可以隐藏某个元素，但隐藏的元素仍需占用与未隐藏之前一样的空间，虽被隐藏但仍旧影响布局。display：none可以隐藏某个元素，且隐藏的元素不会占用任何空间。</p>
<p>块元素：h1(标题)、p（段落）、div（文档中的块级元素）</p>
<p>内联元素：span（文档中的内联元素）、a（书签）</p>
<p>可以随时改变元素的种类，从而使页面以不同的方式进行组合。</p>
<p>Position属性：static（默认位置）、relative（相对正常位置的相对位置）、fixed（相对浏览器是固定位置，即使窗口滚动它也不会滚动）、absolute（绝对定位的元素相对于已定位的父元素，如果没有已定位的父元素，则其位置相对于html）、sticky（粘性定位：依赖于用户的滚动，在relative与fixed之间切换）。</p>
<p>元素的定位与文档流无关，所以可以覆盖页面上其他元素，z-index属性指定了一个元素的堆叠顺序，实现重叠。</p>
<h3 id="CSS布局"><a href="#CSS布局" class="headerlink" title="CSS布局"></a>CSS布局</h3><p>overflow属性用于控制内容溢出元素框时显示的方式，在对应的区间内添加滚动条。</p>
<p>float属性会使元素向左或者向右移动，其周围的元素也会重新排列，往往用于图像或者布局。一个浮动元素会尽量向左或向右移动，直至其外边缘碰到包含框或另一个浮动框的边框。</p>
<p>对齐：1、要水平居中对齐一个元素，可使用margin:auto；并设置到元素的宽度放置它溢出到容器的边缘。2、文本居中对齐，可使用text-align：center；3、图片居中对齐：margin：auto；4、左右对齐：使用定位方式，position：absolute；5、左右对齐：使用float方式；6、垂直居中对齐</p>
<h3 id="CSS组合选择符"><a href="#CSS组合选择符" class="headerlink" title="CSS组合选择符"></a>CSS组合选择符</h3><p>说明了两个选择器直接的关系，包含了四种组合方式：后代选择器、子元素选择器、相邻兄弟选择器、普通兄弟选择器</p>
<h3 id="CSS伪类、伪元素"><a href="#CSS伪类、伪元素" class="headerlink" title="CSS伪类、伪元素"></a>CSS伪类、伪元素</h3><p>添加一些选择器的特殊效果，伪类的语法：selector:pseudo-class {property:value;}；伪元素的语法：selector:pseudo-element {property:value;}</p>
<p>在支持CSS的浏览器中，链接的不同状态可以以不同方式进行显示。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-tag">a</span><span class="selector-pseudo">:link</span> &#123;<span class="attribute">color</span>:<span class="number">#000000</span>;&#125;      <span class="comment">/* 未访问链接*/</span></span></span><br><span class="line"><span class="css"><span class="selector-tag">a</span><span class="selector-pseudo">:visited</span> &#123;<span class="attribute">color</span>:<span class="number">#00FF00</span>;&#125;  <span class="comment">/* 已访问链接 */</span></span></span><br><span class="line"><span class="css"><span class="selector-tag">a</span><span class="selector-pseudo">:hover</span> &#123;<span class="attribute">color</span>:<span class="number">#FF00FF</span>;&#125;  <span class="comment">/* 鼠标移动到链接上 */</span></span></span><br><span class="line"><span class="css"><span class="selector-tag">a</span><span class="selector-pseudo">:active</span> &#123;<span class="attribute">color</span>:<span class="number">#0000FF</span>;&#125;  <span class="comment">/* 鼠标点击时 */</span></span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"/css/"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>&gt;</span>这是一个链接<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">b</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意：<span class="tag">&lt;/<span class="name">b</span>&gt;</span> a:hover 必须在 a:link 和 a:visited 之后，需要严格按顺序才能看到效果。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意：<span class="tag">&lt;/<span class="name">b</span>&gt;</span> a:active 必须在 a:hover 之后。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>伪类可以和CSS类配合使用，以根据链接的被访问与否来判断链接的颜色。</p>
<p>first-child伪类来选择父类的第一个子元素；lang伪类：有能力为不同的语言定义特殊的规则；</p>
<p>first-line伪元素用于向文本的首行设置特殊样式，first-letter伪元素用于向文本首字母设置特殊样式；before伪元素可以在元素内容前面插入新元素；after伪元素可以在元素的内容后面插入新内容；</p>
<h3 id="CSS各类工具"><a href="#CSS各类工具" class="headerlink" title="CSS各类工具"></a>CSS各类工具</h3><h4 id="垂直导航栏实例"><a href="#垂直导航栏实例" class="headerlink" title="垂直导航栏实例"></a>垂直导航栏实例</h4><p>1、先用ul、ui元素构建一个链接列表；</p>
<p>2、利用CSS格式在列表中删除边距和填充；</p>
<p>3、只用a元素的样式，建立一个垂直的导航栏；</p>
<p>4、在点击了选项后，可以添加active类来标准哪个选项被选中；</p>
<p>5、在li、a上添加text-align:center来让链接居中，并在border ul上添加border属性来让导航栏有边框；</p>
<p>6、创建一个左边是全屏高度的固定导航条，右边是可滚动的内容；</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line">body &#123;</span><br><span class="line">    margin: 0;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ul &#123;</span><br><span class="line">    list-style-type: none;</span><br><span class="line">    margin: 0;</span><br><span class="line">    padding: 0;</span><br><span class="line">    width: 25%;</span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#f1f1f1</span>;</span></span><br><span class="line">    position: fixed;</span><br><span class="line">    height: 100%;</span><br><span class="line">    overflow: auto;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">li a &#123;</span><br><span class="line">    display: block;</span><br><span class="line"><span class="css">    <span class="selector-tag">color</span>: <span class="selector-id">#000</span>;</span></span><br><span class="line">    padding: 8px 16px;</span><br><span class="line">    text-decoration: none;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-class">.active</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#4CAF50</span>;</span></span><br><span class="line">    color: white;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">:not(.active)</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#555</span>;</span></span><br><span class="line">    color: white;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">"active"</span> <span class="attr">href</span>=<span class="string">"#home"</span>&gt;</span>主页<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#news"</span>&gt;</span>新闻<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#contact"</span>&gt;</span>联系<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#about"</span>&gt;</span>关于<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">"margin-left:25%;padding:1px 16px;height:1000px;"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h2</span>&gt;</span>Fixed Full-height Side Nav<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h3</span>&gt;</span>Try to scroll this area, and see how the sidenav sticks to the page<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>Notice that this div element has a left margin of 25%. This is because the side navigation is set to 25% width. If you remove the margin, the sidenav will overlay/sit on top of this div.<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>Some text..<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>Some text..<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>Some text..<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>Some text..<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>Some text..<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>Some text..<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>Some text..<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="水平导航栏实例"><a href="#水平导航栏实例" class="headerlink" title="水平导航栏实例"></a>水平导航栏实例</h4><p>1、指定元素，使用float浮动元素；</p>
<p>2、创建一个水平导航条实例，并在鼠标移动到选项之后修改背景颜色，点击选项后添加active类来标准哪个选项被选中；</p>
<p>3、将导航条的最右边选项设置设置右对齐，通过border-right样式来添加分割线</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line">ul &#123;</span><br><span class="line">    list-style-type: none;</span><br><span class="line">    margin: 0;</span><br><span class="line">    padding: 0;</span><br><span class="line">    overflow: hidden;</span><br><span class="line"><span class="css">    <span class="selector-tag">border</span>: 1<span class="selector-tag">px</span> <span class="selector-tag">solid</span> <span class="selector-id">#e7e7e7</span>;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#f3f3f3</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">li &#123;</span><br><span class="line">    float: left;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">li a &#123;</span><br><span class="line">    display: block;</span><br><span class="line"><span class="css">    <span class="selector-tag">color</span>: <span class="selector-id">#666</span>;</span></span><br><span class="line">    text-align: center;</span><br><span class="line">    padding: 14px 16px;</span><br><span class="line">    text-decoration: none;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">:not(.active)</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#ddd</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-class">.active</span> &#123;</span></span><br><span class="line">    color: white;</span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#4CAF50</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">"active"</span> <span class="attr">href</span>=<span class="string">"#home"</span>&gt;</span>主页<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#news"</span>&gt;</span>新闻<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#contact"</span>&gt;</span>联系<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#about"</span>&gt;</span>关于<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="下拉菜单实例"><a href="#下拉菜单实例" class="headerlink" title="下拉菜单实例"></a>下拉菜单实例</h4><p>使用CSS创建一个鼠标移上去后显示下拉菜单的效果，</p>
<p>HTML部分：我们可以使用任何的HTML元素来打开下拉菜单，如span、button元素；使用容器元素来创建下拉菜单的内容，并放在你相放的位置；使用div元素来包裹这些元素并使用CSS来设置下拉内容的样式。</p>
<p>CSS部分：.dropddown类使用position:relative，将设置下拉菜单的内容放置在下拉按钮（position:absolute）的右下位置。.dropdown-content类中是实际的下拉菜单，默认是隐藏的，在鼠标移动到指定元素后会显示。:hover选择器将用于用户将鼠标移动到下拉按钮上时显示下拉菜单。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="comment">/* 下拉按钮样式 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.dropbtn</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#4CAF50</span>;</span></span><br><span class="line">    color: white;</span><br><span class="line">    padding: 16px;</span><br><span class="line">    font-size: 16px;</span><br><span class="line">    border: none;</span><br><span class="line">    cursor: pointer;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* 容器 &lt;div&gt; - 需要定位下拉内容 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.dropdown</span> &#123;</span></span><br><span class="line">    position: relative;</span><br><span class="line">    display: inline-block;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* 下拉内容 (默认隐藏) */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.dropdown-content</span> &#123;</span></span><br><span class="line">    display: none;</span><br><span class="line">    position: absolute;</span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#f9f9f9</span>;</span></span><br><span class="line">    min-width: 160px;</span><br><span class="line"><span class="css">    <span class="selector-tag">box-shadow</span>: 0<span class="selector-tag">px</span> 8<span class="selector-tag">px</span> 16<span class="selector-tag">px</span> 0<span class="selector-tag">px</span> <span class="selector-tag">rgba</span>(0,0,0,0<span class="selector-class">.2</span>);</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* 下拉菜单的链接 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.dropdown-content</span> <span class="selector-tag">a</span> &#123;</span></span><br><span class="line">    color: black;</span><br><span class="line">    padding: 12px 16px;</span><br><span class="line">    text-decoration: none;</span><br><span class="line">    display: block;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* 鼠标移上去后修改下拉菜单链接颜色 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.dropdown-content</span> <span class="selector-tag">a</span><span class="selector-pseudo">:hover</span> &#123;<span class="attribute">background-color</span>: <span class="number">#f1f1f1</span>&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* 在鼠标移上去后显示下拉菜单 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.dropdown</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.dropdown-content</span> &#123;</span></span><br><span class="line">    display: block;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* 当下拉内容显示后修改下拉按钮的背景颜色 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.dropdown</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.dropbtn</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#3e8e41</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"dropdown"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">"dropbtn"</span>&gt;</span>下拉菜单<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"dropdown-content"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>菜鸟教程 1<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>菜鸟教程 2<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>菜鸟教程 3<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="CSS提示工具实例"><a href="#CSS提示工具实例" class="headerlink" title="CSS提示工具实例"></a>CSS提示工具实例</h4><p>1、基础提示框，提示框在鼠标移动到指定元素上显示。</p>
<p>HTML使用容器元素（like div）并添加tooltip类，在鼠标移动到div时显示提示信息；提示文本放在内联元素上（span）并使用class=”tooltiptext”。</p>
<p>CSS中tooltip类使用position:relative，提示文本需要设置定位置position:absolute。tooltiptext类用于实际的提示文本，模式为隐藏的，:hover选择器用于鼠标移动到指定元素div时显示的提示。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="comment">/* Tooltip 容器 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.tooltip</span> &#123;</span></span><br><span class="line">    position: relative;</span><br><span class="line">    display: inline-block;</span><br><span class="line"><span class="css">    <span class="selector-tag">border-bottom</span>: 1<span class="selector-tag">px</span> <span class="selector-tag">dotted</span> <span class="selector-tag">black</span>; <span class="comment">/* 悬停元素上显示点线 */</span></span></span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="css"><span class="comment">/* Tooltip 文本 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.tooltip</span> <span class="selector-class">.tooltiptext</span> &#123;</span></span><br><span class="line">    visibility: hidden;</span><br><span class="line">    width: 120px;</span><br><span class="line">    background-color: black;</span><br><span class="line"><span class="css">    <span class="selector-tag">color</span>: <span class="selector-id">#fff</span>;</span></span><br><span class="line">    text-align: center;</span><br><span class="line">    padding: 5px 0;</span><br><span class="line">    border-radius: 6px;</span><br><span class="line"> </span><br><span class="line"><span class="css">    <span class="comment">/* 定位 */</span></span></span><br><span class="line">    position: absolute;</span><br><span class="line">    z-index: 1;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="css"><span class="comment">/* 鼠标移动上去后显示提示框 */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.tooltip</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.tooltiptext</span> &#123;</span></span><br><span class="line">    visibility: visible;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"tooltip"</span>&gt;</span>鼠标移动到这</span><br><span class="line">  <span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">"tooltiptext"</span>&gt;</span>提示文本<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>2、定位提示工具：通过修改容器元素的top、left、right值来修改提示框显示的位置；如果想要提示框显示在头部和底部，需要使用margin-left属性，并设置为-60px</p>
<p>3、可以使用CSS伪元素::after以及content属性为提示工具创建一个小箭头标志，箭头由边框组成，但组合起来后提示工具像语音提示框。</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.tooltip</span> <span class="selector-class">.tooltiptext</span><span class="selector-pseudo">::after</span> &#123;</span><br><span class="line">    <span class="attribute">content</span>: <span class="string">" "</span>;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">100%</span>; <span class="comment">/* 提示工具底部 */</span></span><br><span class="line">    <span class="attribute">left</span>: <span class="number">50%</span>;</span><br><span class="line">    <span class="attribute">margin-left</span>: -<span class="number">5px</span>;</span><br><span class="line">    <span class="attribute">border-width</span>: <span class="number">5px</span>;</span><br><span class="line">    <span class="attribute">border-style</span>: solid;</span><br><span class="line">    <span class="attribute">border-color</span>: black transparent transparent transparent;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="图片廊"><a href="#图片廊" class="headerlink" title="图片廊"></a>图片廊</h3><p>1、CSS创建图片廊：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"responsive"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"img"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"http://static.runoob.com/images/demo/demo1.jpg"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"http://static.runoob.com/images/demo/demo1.jpg"</span> <span class="attr">alt</span>=<span class="string">"图片文本描述"</span> <span class="attr">width</span>=<span class="string">"300"</span> <span class="attr">height</span>=<span class="string">"200"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"desc"</span>&gt;</span>这里添加图片文本描述<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"responsive"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"img"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"http://static.runoob.com/images/demo/demo2.jpg"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"http://static.runoob.com/images/demo/demo2.jpg"</span> <span class="attr">alt</span>=<span class="string">"图片文本描述"</span> <span class="attr">width</span>=<span class="string">"300"</span> <span class="attr">height</span>=<span class="string">"200"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"desc"</span>&gt;</span>这里添加图片文本描述<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"responsive"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"img"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"http://static.runoob.com/images/demo/demo3.jpg"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"http://static.runoob.com/images/demo/demo3.jpg"</span> <span class="attr">alt</span>=<span class="string">"图片文本描述"</span> <span class="attr">width</span>=<span class="string">"300"</span> <span class="attr">height</span>=<span class="string">"200"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"desc"</span>&gt;</span>这里添加图片文本描述<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"responsive"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"img"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"http://static.runoob.com/images/demo/demo4.jpg"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"http://static.runoob.com/images/demo/demo4.jpg"</span> <span class="attr">alt</span>=<span class="string">"图片文本描述"</span> <span class="attr">width</span>=<span class="string">"300"</span> <span class="attr">height</span>=<span class="string">"200"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"desc"</span>&gt;</span>这里添加图片文本描述<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>2、使用CSS3的媒体查询来创建响应式图片廊</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"responsive"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"img"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"img_fjords.jpg"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"http://www.runoob.com/wp-content/uploads/2016/04/img_fjords.jpg"</span> <span class="attr">alt</span>=<span class="string">"Trolltunga Norway"</span> <span class="attr">width</span>=<span class="string">"300"</span> <span class="attr">height</span>=<span class="string">"200"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"desc"</span>&gt;</span>这里添加图片文本描述<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"responsive"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"img"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"img_forest.jpg"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"http://www.runoob.com/wp-content/uploads/2016/04/img_forest.jpg"</span> <span class="attr">alt</span>=<span class="string">"Forest"</span> <span class="attr">width</span>=<span class="string">"600"</span> <span class="attr">height</span>=<span class="string">"400"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"desc"</span>&gt;</span>这里添加图片文本描述<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"responsive"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"img"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"img_lights.jpg"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"http://www.runoob.com/wp-content/uploads/2016/04/img_lights.jpg"</span> <span class="attr">alt</span>=<span class="string">"Northern Lights"</span> <span class="attr">width</span>=<span class="string">"600"</span> <span class="attr">height</span>=<span class="string">"400"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"desc"</span>&gt;</span>这里添加图片文本描述<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"responsive"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"img"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"img_mountains.jpg"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"http://www.runoob.com/wp-content/uploads/2016/04/img_mountains.jpg"</span> <span class="attr">alt</span>=<span class="string">"Mountains"</span> <span class="attr">width</span>=<span class="string">"600"</span> <span class="attr">height</span>=<span class="string">"400"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"desc"</span>&gt;</span>这里添加图片文本描述<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"clearfix"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">"padding:6px;"</span>&gt;</span></span><br><span class="line">  </span><br><span class="line">  <span class="tag">&lt;<span class="name">h4</span>&gt;</span>重置浏览器大小查看效果<span class="tag">&lt;/<span class="name">h4</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>CSS3中属性的透明度是opacity，同时可以利用hover属性增加当用户将鼠标悬停在其中一个图像时会发生什么的时间，此时调为opacity=1</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">img</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="attribute">opacity</span>:<span class="number">0.4</span>;</span><br><span class="line">  <span class="attribute">filter</span>:<span class="built_in">alpha</span>(opacity=<span class="number">40</span>); <span class="comment">/*  IE8 及其更早版本 */</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">img</span><span class="selector-pseudo">:hover</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="attribute">opacity</span>:<span class="number">1.0</span>;</span><br><span class="line">  <span class="attribute">filter</span>:<span class="built_in">alpha</span>(opacity=<span class="number">100</span>); <span class="comment">/* IE8 及其更早版本 */</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>透明盒子中的文字：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-tag">div</span><span class="selector-class">.background</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">  <span class="selector-tag">width</span><span class="selector-pseudo">:500px</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">height</span><span class="selector-pseudo">:250px</span>;</span></span><br><span class="line">  background:url(https://www.runoob.com/images/klematis.jpg) repeat;</span><br><span class="line"><span class="css">  <span class="selector-tag">border</span><span class="selector-pseudo">:2px</span> <span class="selector-tag">solid</span> <span class="selector-tag">black</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="css"><span class="selector-tag">div</span><span class="selector-class">.transbox</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">  <span class="selector-tag">width</span><span class="selector-pseudo">:400px</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">height</span><span class="selector-pseudo">:180px</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">margin</span><span class="selector-pseudo">:30px</span> 50<span class="selector-tag">px</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">background-color</span>:<span class="selector-id">#ffffff</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">border</span><span class="selector-pseudo">:1px</span> <span class="selector-tag">solid</span> <span class="selector-tag">black</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">opacity</span><span class="selector-pseudo">:0.6</span>;</span></span><br><span class="line">  filter:alpha(opacity=60); /* IE8 及更早版本 */</span><br><span class="line">&#125;</span><br><span class="line"><span class="css"><span class="selector-tag">div</span><span class="selector-class">.transbox</span> <span class="selector-tag">p</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">  <span class="selector-tag">margin</span><span class="selector-pseudo">:30px</span> 40<span class="selector-tag">px</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">font-weight</span><span class="selector-pseudo">:bold</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">color</span>:<span class="selector-id">#000000</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"background"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"transbox"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。这些文本在透明框里。</span><br><span class="line"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>图像拼合技术：单个图像的集合，多个图像的网页会降低服务器的请求数量，并节省带宽。与其使用三个独立图像不如使用这种单个图像。</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">img</span><span class="selector-class">.home</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="attribute">width</span>:<span class="number">46px</span>;</span><br><span class="line"><span class="attribute">height</span>:<span class="number">44px</span>;</span><br><span class="line"><span class="attribute">background</span>:<span class="built_in">url</span>(img_navsprites.gif) <span class="number">0</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>:hover选择器可以运用于所有元素，因此所有元素都可以显示鼠标悬停在元素上的显示效果。</p>
<h3 id="CSS媒体"><a href="#CSS媒体" class="headerlink" title="CSS媒体"></a>CSS媒体</h3><p>允许指定文件如何在不同媒体中实现，而一些CSS属性只设计了某些媒体，而其他的属性可用于许多不同的媒体类型。</p>
<p>@media规则允许在相同样式表为不同媒体设置不同的样式</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">@media</span> screen</span><br><span class="line">&#123;</span><br><span class="line">    <span class="selector-tag">p</span><span class="selector-class">.test</span> &#123;<span class="attribute">font-family</span>:verdana,sans-serif;<span class="attribute">font-size</span>:<span class="number">14px</span>;&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">@media</span> print</span><br><span class="line">&#123;</span><br><span class="line">    <span class="selector-tag">p</span><span class="selector-class">.test</span> &#123;<span class="attribute">font-family</span>:times,serif;<span class="attribute">font-size</span>:<span class="number">10px</span>;&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">@media</span> screen,print</span><br><span class="line">&#123;</span><br><span class="line">    <span class="selector-tag">p</span><span class="selector-class">.test</span> &#123;<span class="attribute">font-weight</span>:bold;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="CSS属性选择性"><a href="#CSS属性选择性" class="headerlink" title="CSS属性选择性"></a>CSS属性选择性</h3><p>具有特定属性的HTML元素样式不仅仅是class和id，下面的实例改变了标题title=’runoob‘元素的边框样式</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-attr">[title=runoob]</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="attribute">border</span>:<span class="number">5px</span> solid green;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>表单样式：属性选择器无需使用class或id的形式。</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">input</span><span class="selector-attr">[type=<span class="string">"text"</span>]</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="attribute">width</span>:<span class="number">150px</span>;</span><br><span class="line">    <span class="attribute">display</span>:block;</span><br><span class="line">    <span class="attribute">margin-bottom</span>:<span class="number">10px</span>;</span><br><span class="line">    <span class="attribute">background-color</span>:yellow;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">input</span><span class="selector-attr">[type=<span class="string">"button"</span>]</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="attribute">width</span>:<span class="number">120px</span>;</span><br><span class="line">    <span class="attribute">margin-left</span>:<span class="number">35px</span>;</span><br><span class="line">    <span class="attribute">display</span>:block;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可用CSS属性选择器来渲染HTML的表单元素，使用width属性设置输入框的宽度；使用padding属性可以在输入框中添加内边距；使用border属性可以修改input边框得大小或颜色；使用background-color属性设置输入框得背景颜色；</p>
<h3 id="CSS计数器"><a href="#CSS计数器" class="headerlink" title="CSS计数器"></a>CSS计数器</h3><p>CSS计数器根据规则来递增变量，以下实例在页面创建一个计数器，且每个h2元素计数值都会递归，并在每个h2元素前添加Section计数值。</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">  <span class="attribute">counter-reset</span>: section;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="selector-tag">h2</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">  <span class="attribute">counter-increment</span>: section;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">"Section "</span> <span class="built_in">counter</span>(section) <span class="string">": "</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>嵌套计数器：在每一个h1元素前添加计数值Section，嵌套得计数值则放在h2元素得前面，内容为 主标题计数值、副标题计数值。</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">  <span class="attribute">counter-reset</span>: section;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="selector-tag">h1</span> &#123;</span><br><span class="line">  <span class="attribute">counter-reset</span>: subsection;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="selector-tag">h1</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">  <span class="attribute">counter-increment</span>: section;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">"Section "</span> <span class="built_in">counter</span>(section) <span class="string">". "</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="selector-tag">h2</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">  <span class="attribute">counter-increment</span>: subsection;</span><br><span class="line">  <span class="attribute">content</span>: <span class="built_in">counter</span>(section) <span class="string">"."</span> <span class="built_in">counter</span>(subsection) <span class="string">" "</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="2、CSS网页布局"><a href="#2、CSS网页布局" class="headerlink" title="2、CSS网页布局"></a>2、CSS网页布局</h2><p>网页布局一般分为以下几个部分：头部区域、菜单导航区域、内容区域、底部区域。</p>
<p>1、头部区域一般位于整个网页得顶部，用于设置网页得标题或LOGO；</p>
<p>2、菜单导航区域包含了一些链接，引导用户浏览其他页面；</p>
<p>3、内容区域一般有三种形式，1列用于移动端；2列用于平板设备；3列用于PC桌面设备。</p>
<p>4、底部区域在网页的最下方，一般包含版权信息与联系方式；</p>
<p>通过以上的方式，我们创建了一个响应式等页面，</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line">* &#123;</span><br><span class="line">  <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">  <span class="attribute">font-family</span>: Arial;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">background</span>: <span class="number">#f1f1f1</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 头部标题 */</span></span><br><span class="line"><span class="selector-class">.header</span> &#123;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">30px</span>;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">background</span>: white;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="selector-class">.header</span> <span class="selector-tag">h1</span> &#123;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">50px</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 导航条 */</span></span><br><span class="line"><span class="selector-class">.topnav</span> &#123;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#333</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 导航条链接 */</span></span><br><span class="line"><span class="selector-class">.topnav</span> <span class="selector-tag">a</span> &#123;</span><br><span class="line">  <span class="attribute">float</span>: left;</span><br><span class="line">  <span class="attribute">display</span>: block;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#f2f2f2</span>;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">14px</span> <span class="number">16px</span>;</span><br><span class="line">  <span class="attribute">text-decoration</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 链接颜色修改 */</span></span><br><span class="line"><span class="selector-class">.topnav</span> <span class="selector-tag">a</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#ddd</span>;</span><br><span class="line">  <span class="attribute">color</span>: black;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 创建两列 */</span></span><br><span class="line"><span class="comment">/* Left column */</span></span><br><span class="line"><span class="selector-class">.leftcolumn</span> &#123;   </span><br><span class="line">  <span class="attribute">float</span>: left;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">75%</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 右侧栏 */</span></span><br><span class="line"><span class="selector-class">.rightcolumn</span> &#123;</span><br><span class="line">  <span class="attribute">float</span>: left;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">25%</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#f1f1f1</span>;</span><br><span class="line">  <span class="attribute">padding-left</span>: <span class="number">20px</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 图像部分 */</span></span><br><span class="line"><span class="selector-class">.fakeimg</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#aaa</span>;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">20px</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 文章卡片效果 */</span></span><br><span class="line"><span class="selector-class">.card</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: white;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">margin-top</span>: <span class="number">20px</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 列后面清除浮动 */</span></span><br><span class="line"><span class="selector-class">.row</span><span class="selector-pseudo">:after</span> &#123;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">""</span>;</span><br><span class="line">  <span class="attribute">display</span>: table;</span><br><span class="line">  <span class="attribute">clear</span>: both;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 底部 */</span></span><br><span class="line"><span class="selector-class">.footer</span> &#123;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">background</span>: <span class="number">#ddd</span>;</span><br><span class="line">  <span class="attribute">margin-top</span>: <span class="number">20px</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 响应式布局 - 屏幕尺寸小于 800px 时，两列布局改为上下布局 */</span></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width:</span> <span class="number">800px</span>) &#123;</span><br><span class="line">  <span class="selector-class">.leftcolumn</span>, <span class="selector-class">.rightcolumn</span> &#123;   </span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">/* 响应式布局 -屏幕尺寸小于 400px 时，导航等布局改为上下布局 */</span></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width:</span> <span class="number">400px</span>) &#123;</span><br><span class="line">  <span class="selector-class">.topnav</span> <span class="selector-tag">a</span> &#123;</span><br><span class="line">    <span class="attribute">float</span>: none;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3、CSS总结"><a href="#3、CSS总结" class="headerlink" title="3、CSS总结"></a>3、CSS总结</h2><p>已经实现了，如何创建样式表来同时控制多重页面的样式和布局，比如如何定位元素、控制元素的可见性和尺寸、设置元素的形状、将一个元素置于另一个元素之后，以及向某些选择器添加特殊的效果，比如；链接。</p>
<p>CSS实例类型索引：runoob.com/css/css-examples.html。</p>
<h2 id="4、CSS3教程"><a href="#4、CSS3教程" class="headerlink" title="4、CSS3教程"></a>4、CSS3教程</h2><p>CSS3用于控制网页样式和布局，CSS3被拆分为“模块”，旧规范已拆分为小块，还增加了新的。最重要的CSS3模块如下：选择器、盒模型、背景和边框、文字特效、2D3D转换、动画、多列布局、用户界面。</p>
<h3 id="CSS格式背景"><a href="#CSS格式背景" class="headerlink" title="CSS格式背景"></a>CSS格式背景</h3><p>边框：在CSS3中可添加圆角边框，添加阴影框，并作为边界形象而不使用设计程序。border-radius属性用于创建圆角；box-shadow属性用来添加阴影；border-image属性用于创建边框，允许你指定一个图片作为边框，用于创建上文边框的原始图像。</p>
<p>背景：包含新背景属性，提供更大背景元素控制。background-image添加背景图片；background-size指定背景图像大小；background-origin指定背景图像的位置区域；且CSS3允许在元素上添加多个背景图像。background-clip背景裁剪属性是从指定位置开始绘制。</p>
<p>渐变：可在两个或多个指定颜色之间显示平稳的过渡，linear gradients线性渐变：上、下、左、右、对角，radial gradients由中心定义。同样也可以定义一个角度而不用预定义方向：background-image: linear-gradient(angle, color-stop1, color-stop2);同样也可以使用多个颜色节点的定义、支持透明度以创建减弱变淡效果transparent，repeating-linear-gradient()函数用于重复线性渐变。</p>
<p>文本效果：text-shadow文本阴影、box-shadow盒子阴影、也可以在::before和::after两个伪元素中添加阴影效果</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-id">#boxshadow</span> &#123;</span></span><br><span class="line">    position: relative;</span><br><span class="line"><span class="css">    <span class="selector-tag">-moz-box-shadow</span>: 1<span class="selector-tag">px</span> 2<span class="selector-tag">px</span> 4<span class="selector-tag">px</span> <span class="selector-tag">rgba</span>(0, 0, 0,0<span class="selector-class">.5</span>);</span></span><br><span class="line"><span class="css">    <span class="selector-tag">-webkit-box-shadow</span>: 1<span class="selector-tag">px</span> 2<span class="selector-tag">px</span> 4<span class="selector-tag">px</span> <span class="selector-tag">rgba</span>(0, 0, 0, <span class="selector-class">.5</span>);</span></span><br><span class="line"><span class="css">    <span class="selector-tag">box-shadow</span>: 1<span class="selector-tag">px</span> 2<span class="selector-tag">px</span> 4<span class="selector-tag">px</span> <span class="selector-tag">rgba</span>(0, 0, 0, <span class="selector-class">.5</span>);</span></span><br><span class="line">    padding: 10px;</span><br><span class="line">    background: white;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* Make the image fit the box */</span></span></span><br><span class="line"><span class="css"><span class="selector-id">#boxshadow</span> <span class="selector-tag">img</span> &#123;</span></span><br><span class="line">    width: 100%;</span><br><span class="line"><span class="css">    <span class="selector-tag">border</span>: 1<span class="selector-tag">px</span> <span class="selector-tag">solid</span> <span class="selector-id">#8a4419</span>;</span></span><br><span class="line">    border-style: inset;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-id">#boxshadow</span><span class="selector-pseudo">::after</span> &#123;</span></span><br><span class="line">    content: '';</span><br><span class="line">    position: absolute;</span><br><span class="line"><span class="css">    <span class="selector-tag">z-index</span>: <span class="selector-tag">-1</span>; <span class="comment">/* hide shadow behind image */</span></span></span><br><span class="line"><span class="css">    <span class="selector-tag">-webkit-box-shadow</span>: 0 15<span class="selector-tag">px</span> 20<span class="selector-tag">px</span> <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.3</span>);</span></span><br><span class="line"><span class="css">    <span class="selector-tag">-moz-box-shadow</span>: 0 15<span class="selector-tag">px</span> 20<span class="selector-tag">px</span> <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.3</span>);</span></span><br><span class="line"><span class="css">    <span class="selector-tag">box-shadow</span>: 0 15<span class="selector-tag">px</span> 20<span class="selector-tag">px</span> <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.3</span>);</span></span><br><span class="line">    width: 70%;</span><br><span class="line"><span class="css">    <span class="selector-tag">left</span>: 15%; <span class="comment">/* one half of the remaining 30% */</span></span></span><br><span class="line">    height: 100px;</span><br><span class="line">    bottom: 0;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"boxshadow"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"rock600x400.jpg"</span> <span class="attr">alt</span>=<span class="string">"Norway"</span> <span class="attr">width</span>=<span class="string">"600"</span> <span class="attr">height</span>=<span class="string">"400"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>阴影使用的一个特例是卡片效果，</p>
<p>CSS文本溢出属性Text Overflow指定应向用户如何显示溢出内容；自动换行属性word-wrap允许强制文本换行，即使分裂中间一个字。</p>
<p>CSS3单词拆分换行属性指定换行规则：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span> </span><br><span class="line"><span class="css"><span class="selector-tag">p</span><span class="selector-class">.test1</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">width</span><span class="selector-pseudo">:9em</span>; </span></span><br><span class="line"><span class="css">	<span class="selector-tag">border</span><span class="selector-pseudo">:1px</span> <span class="selector-tag">solid</span> <span class="selector-id">#000000</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">word-break</span><span class="selector-pseudo">:keep-all</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">p</span><span class="selector-class">.test2</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">width</span><span class="selector-pseudo">:9em</span>; </span></span><br><span class="line"><span class="css">	<span class="selector-tag">border</span><span class="selector-pseudo">:1px</span> <span class="selector-tag">solid</span> <span class="selector-id">#000000</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">word-break</span><span class="selector-pseudo">:break-all</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"test1"</span>&gt;</span> This paragraph contains some text. This line will-break-at-hyphenates.<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"test2"</span>&gt;</span> This paragraph contains some text: The lines will break at any character.<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意:<span class="tag">&lt;/<span class="name">b</span>&gt;</span>  word-break 属性不兼容 Opera.<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>CSS3字体：自己的字体是在@font-face规则中描述定义的，必须首先定义字体的名称然后指向该字体文字文件。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span> </span><br><span class="line"><span class="css"><span class="keyword">@font-face</span></span></span><br><span class="line">&#123;</span><br><span class="line">	font-family: myFirstFont;</span><br><span class="line">	src: url('Sansation_Light.ttf')</span><br><span class="line">		,url('Sansation_Light.eot'); /* IE9 */</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">div</span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">font-family</span><span class="selector-pseudo">:myFirstFont</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意:<span class="tag">&lt;/<span class="name">b</span>&gt;</span> Internet Explorer 9 只支持 .eot 格式的字体.<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">使用 CSS3,网站终于可以使用字体以外的预先选择“合法”字体</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="CSS32D、3D转换"><a href="#CSS32D、3D转换" class="headerlink" title="CSS32D、3D转换"></a>CSS32D、3D转换</h3><p>CSS3转换可以对元素进行移动、缩放、转动、拉长或拉伸，转换的效果是让某个元素改变形状、大小和位置。</p>
<p>2D变换：</p>
<p>translate()：根据X、Y轴位置给定的参数，从当前元素位置移动；rotate()：在一个给定度数顺时针旋转的元素，参数为负值则为逆时针；scale(）:增减元素的大小；skew()方法：包含两个参数值，分别表示X轴和Y轴倾斜的角度；matrix()方法和2D变换方法合并成一个，有6个参数包含旋转、缩放、移动、倾斜功能；</p>
<p>3D变换：能够将图片视为一个3D的小纸片进行翻转、变换运动，而不只是旋转与改变大小。</p>
<p>rotateX()方法：围绕其在一个给定度数X轴旋转的元素；</p>
<p>rotateY()方法：围绕其在一个给定度数Y轴旋转的元素；</p>
<h2 id="5、CSS3动画"><a href="#5、CSS3动画" class="headerlink" title="5、CSS3动画"></a>5、CSS3动画</h2><h3 id="CSS3过渡"><a href="#CSS3过渡" class="headerlink" title="CSS3过渡"></a>CSS3过渡</h3><p>元素从一种样式逐渐改变成另一种的效果，指定添加效果的CSS属性、指定效果的持续时间。要添加多个样式的变换效果，添加的属性由逗号分隔。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span> </span><br><span class="line">div</span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">width</span><span class="selector-pseudo">:100px</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">height</span><span class="selector-pseudo">:100px</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">background</span><span class="selector-pseudo">:red</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">transition</span><span class="selector-pseudo">:width</span> 2<span class="selector-tag">s</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">-webkit-transition</span><span class="selector-pseudo">:width</span> 2<span class="selector-tag">s</span>; <span class="comment">/* Safari */</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">div</span><span class="selector-pseudo">:hover</span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">width</span><span class="selector-pseudo">:300px</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意：<span class="tag">&lt;/<span class="name">b</span>&gt;</span>该实例无法在 Internet Explorer 9 及更早 IE 版本上工作。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>鼠标移动到 div 元素上，查看过渡效果。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="CSS3创建动画"><a href="#CSS3创建动画" class="headerlink" title="CSS3创建动画"></a>CSS3创建动画</h3><p>@keyframes规则：创建动画，其内指定一个CSS样式和动画将逐步从目前的样式更改为新的样式；</p>
<p>当在@keyframes创建动画，把它绑定到一个选择器，否则动画不会有任何效果，指定这2个CSS3的动画属性绑定向一个选择器：规定动画名称与时长。下例将myfirst动画捆绑到div元素，时长为5秒。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span> </span><br><span class="line">div</span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">width</span><span class="selector-pseudo">:100px</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">height</span><span class="selector-pseudo">:100px</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">background</span><span class="selector-pseudo">:red</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">animation</span><span class="selector-pseudo">:myfirst</span> 5<span class="selector-tag">s</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">-webkit-animation</span><span class="selector-pseudo">:myfirst</span> 5<span class="selector-tag">s</span>; <span class="comment">/* Safari and Chrome */</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@keyframes</span> myfirst</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">from</span> &#123;<span class="attribute">background</span>:red;&#125;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">to</span> &#123;<span class="attribute">background</span>:yellow;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@-webkit-keyframes</span> myfirst /* Safari <span class="keyword">and</span> Chrome */</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">from</span> &#123;<span class="attribute">background</span>:red;&#125;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">to</span> &#123;<span class="attribute">background</span>:yellow;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意:<span class="tag">&lt;/<span class="name">b</span>&gt;</span> 该实例在 Internet Explorer 9 及更早 IE 版本是无效的。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>动画的实质是元素从一种样式逐渐变化为另一种样式的效果，可以改变任意多的样式、次数，并用百分比来规定变化发生的事件。以下可以改变元素背景色与位置：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span> </span><br><span class="line">div</span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">width</span><span class="selector-pseudo">:100px</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">height</span><span class="selector-pseudo">:100px</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">background</span><span class="selector-pseudo">:red</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">position</span><span class="selector-pseudo">:relative</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">animation</span><span class="selector-pseudo">:myfirst</span> 5<span class="selector-tag">s</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">-webkit-animation</span><span class="selector-pseudo">:myfirst</span> 5<span class="selector-tag">s</span>; <span class="comment">/* Safari and Chrome */</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@keyframes</span> myfirst</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	0%   &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	25%  &#123;<span class="attribute">background</span>:yellow; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	50%  &#123;<span class="attribute">background</span>:blue; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	75%  &#123;<span class="attribute">background</span>:green; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	100% &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@-webkit-keyframes</span> myfirst /* Safari <span class="keyword">and</span> Chrome */</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	0%   &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	25%  &#123;<span class="attribute">background</span>:yellow; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	50%  &#123;<span class="attribute">background</span>:blue; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	75%  &#123;<span class="attribute">background</span>:green; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	100% &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意:<span class="tag">&lt;/<span class="name">b</span>&gt;</span> 该实例在 Internet Explorer 9 及更早 IE 版本是无效的。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>使用下例设置所有的属性，并使用了简写的动画animation属性。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span> </span><br><span class="line">div</span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	<span class="selector-tag">width</span><span class="selector-pseudo">:100px</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">height</span><span class="selector-pseudo">:100px</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">background</span><span class="selector-pseudo">:red</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">position</span><span class="selector-pseudo">:relative</span>;</span></span><br><span class="line"><span class="css">	<span class="selector-tag">animation</span><span class="selector-pseudo">:myfirst</span> 5<span class="selector-tag">s</span> <span class="selector-tag">linear</span> 2<span class="selector-tag">s</span> <span class="selector-tag">infinite</span> <span class="selector-tag">alternate</span>;</span></span><br><span class="line"><span class="css">	<span class="comment">/* Firefox: */</span></span></span><br><span class="line"><span class="css">	<span class="selector-tag">-moz-animation</span><span class="selector-pseudo">:myfirst</span> 5<span class="selector-tag">s</span> <span class="selector-tag">linear</span> 2<span class="selector-tag">s</span> <span class="selector-tag">infinite</span> <span class="selector-tag">alternate</span>;</span></span><br><span class="line"><span class="css">	<span class="comment">/* Safari and Chrome: */</span></span></span><br><span class="line"><span class="css">	<span class="selector-tag">-webkit-animation</span><span class="selector-pseudo">:myfirst</span> 5<span class="selector-tag">s</span> <span class="selector-tag">linear</span> 2<span class="selector-tag">s</span> <span class="selector-tag">infinite</span> <span class="selector-tag">alternate</span>;</span></span><br><span class="line"><span class="css">	<span class="comment">/* Opera: */</span></span></span><br><span class="line"><span class="css">	<span class="selector-tag">-o-animation</span><span class="selector-pseudo">:myfirst</span> 5<span class="selector-tag">s</span> <span class="selector-tag">linear</span> 2<span class="selector-tag">s</span> <span class="selector-tag">infinite</span> <span class="selector-tag">alternate</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@keyframes</span> myfirst</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	0%   &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	25%  &#123;<span class="attribute">background</span>:yellow; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	50%  &#123;<span class="attribute">background</span>:blue; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	75%  &#123;<span class="attribute">background</span>:green; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	100% &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@-moz-keyframes</span> myfirst /* Firefox */</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	0%   &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	25%  &#123;<span class="attribute">background</span>:yellow; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	50%  &#123;<span class="attribute">background</span>:blue; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	75%  &#123;<span class="attribute">background</span>:green; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	100% &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@-webkit-keyframes</span> myfirst /* Safari <span class="keyword">and</span> Chrome */</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	0%   &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	25%  &#123;<span class="attribute">background</span>:yellow; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	50%  &#123;<span class="attribute">background</span>:blue; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	75%  &#123;<span class="attribute">background</span>:green; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	100% &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@-o-keyframes</span> myfirst /* Opera */</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="css">	0%   &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	25%  &#123;<span class="attribute">background</span>:yellow; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line"><span class="css">	50%  &#123;<span class="attribute">background</span>:blue; <span class="attribute">left</span>:<span class="number">200px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	75%  &#123;<span class="attribute">background</span>:green; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">200px</span>;&#125;</span></span><br><span class="line"><span class="css">	100% &#123;<span class="attribute">background</span>:red; <span class="attribute">left</span>:<span class="number">0px</span>; <span class="attribute">top</span>:<span class="number">0px</span>;&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意:<span class="tag">&lt;/<span class="name">b</span>&gt;</span> 该实例在 Internet Explorer 9 及更早 IE 版本是无效的。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="CSS用户界面与布局"><a href="#CSS用户界面与布局" class="headerlink" title="CSS用户界面与布局"></a>CSS用户界面与布局</h3><h4 id="1、多列布局"><a href="#1、多列布局" class="headerlink" title="1、多列布局"></a>1、多列布局</h4><p>CSS3可将文本内容设计成像报纸一样的多列布局；column-count：指定需要分割的列数，column-gap：指定列与列之间间隙；column-rule-style：指定列与列间边框样式；</p>
<h4 id="2、resize"><a href="#2、resize" class="headerlink" title="2、resize"></a>2、resize</h4><p>指定一个元素是否应该由用户去调整大小；box-sizing属性：允许以确切的方式适应某区域的具体内容；outline-offset属性对轮廓进行偏移，并在超出边缘的位置绘制轮廓。</p>
<h4 id="3、CSS3来布局图片"><a href="#3、CSS3来布局图片" class="headerlink" title="3、CSS3来布局图片"></a>3、CSS3来布局图片</h4><p>：border-radius来设置圆角、椭圆形图片；border属性来创建缩略图,在图片外层添加一个链接；</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line">a &#123;</span><br><span class="line">    display: inline-block;</span><br><span class="line"><span class="css">    <span class="selector-tag">border</span>: 1<span class="selector-tag">px</span> <span class="selector-tag">solid</span> <span class="selector-id">#ddd</span>;</span></span><br><span class="line">    border-radius: 4px;</span><br><span class="line">    padding: 5px;</span><br><span class="line"><span class="css">    <span class="selector-tag">transition</span>: 0<span class="selector-class">.3s</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">a</span><span class="selector-pseudo">:hover</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">box-shadow</span>: 0 0 2<span class="selector-tag">px</span> 1<span class="selector-tag">px</span> <span class="selector-tag">rgba</span>(0, 140, 186, 0<span class="selector-class">.5</span>);</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>缩略图作为连接<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>我们使用 border 属性来创建缩略图。在图片外层添加一个链接。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>点击图片查看效果：<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">target</span>=<span class="string">"_blank"</span> <span class="attr">href</span>=<span class="string">"paris.jpg"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"paris.jpg"</span> <span class="attr">alt</span>=<span class="string">"Paris"</span> <span class="attr">width</span>=<span class="string">"400"</span> <span class="attr">height</span>=<span class="string">"300"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>响应式图片会自动适应不同尺寸屏幕，</p>
<h4 id="4、卡片式图片"><a href="#4、卡片式图片" class="headerlink" title="4、卡片式图片"></a>4、卡片式图片</h4><p>并在图片下方添加图片描述文字。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-tag">body</span> &#123;<span class="attribute">margin</span>:<span class="number">25px</span>;&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">div</span><span class="selector-class">.polaroid</span> &#123;</span></span><br><span class="line">  width: 80%;</span><br><span class="line">  background-color: white;</span><br><span class="line"><span class="css">  <span class="selector-tag">box-shadow</span>: 0 4<span class="selector-tag">px</span> 8<span class="selector-tag">px</span> 0 <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.2</span>), 0 6<span class="selector-tag">px</span> 20<span class="selector-tag">px</span> 0 <span class="selector-tag">rgba</span>(0, 0, 0, 0<span class="selector-class">.19</span>);</span></span><br><span class="line">  margin-bottom: 25px;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">div</span><span class="selector-class">.container</span> &#123;</span></span><br><span class="line">  text-align: center;</span><br><span class="line">  padding: 10px 20px;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>响应式卡片<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"polaroid"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"rock600x400.jpg"</span> <span class="attr">alt</span>=<span class="string">"Norway"</span> <span class="attr">style</span>=<span class="string">"width:100%"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"container"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>The Troll's tongue in Hardanger, Norway<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"polaroid"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"lights600x400.jpg"</span> <span class="attr">alt</span>=<span class="string">"Norway"</span> <span class="attr">style</span>=<span class="string">"width:100%"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"container"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>Northern Lights in Norway<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>CSS filter属性用于为元素添加可视效果，模糊、饱和度。</p>
<p>如何结合CSS和JavaScript来一起渲染图片：首先用CSS来创建modal窗口，默认为隐藏，然后使用JavaScript来显示模态窗口，当点击图片时，图片会在弹出的窗口中显示。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-id">#myImg</span> &#123;</span></span><br><span class="line">    border-radius: 5px;</span><br><span class="line">    cursor: pointer;</span><br><span class="line"><span class="css">    <span class="selector-tag">transition</span>: 0<span class="selector-class">.3s</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-id">#myImg</span><span class="selector-pseudo">:hover</span> &#123;<span class="attribute">opacity</span>: <span class="number">0.7</span>;&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* The Modal (background) */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.modal</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">display</span>: <span class="selector-tag">none</span>; <span class="comment">/* Hidden by default */</span></span></span><br><span class="line"><span class="css">    <span class="selector-tag">position</span>: <span class="selector-tag">fixed</span>; <span class="comment">/* Stay in place */</span></span></span><br><span class="line"><span class="css">    <span class="selector-tag">z-index</span>: 1; <span class="comment">/* Sit on top */</span></span></span><br><span class="line"><span class="css">    <span class="selector-tag">padding-top</span>: 100<span class="selector-tag">px</span>; <span class="comment">/* Location of the box */</span></span></span><br><span class="line">    left: 0;</span><br><span class="line">    top: 0;</span><br><span class="line"><span class="css">    <span class="selector-tag">width</span>: 100%; <span class="comment">/* Full width */</span></span></span><br><span class="line"><span class="css">    <span class="selector-tag">height</span>: 100%; <span class="comment">/* Full height */</span></span></span><br><span class="line"><span class="css">    <span class="selector-tag">overflow</span>: <span class="selector-tag">auto</span>; <span class="comment">/* Enable scroll if needed */</span></span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-tag">rgb</span>(0,0,0); <span class="comment">/* Fallback color */</span></span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-tag">rgba</span>(0,0,0,0<span class="selector-class">.9</span>); <span class="comment">/* Black w/ opacity */</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* Modal Content (image) */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.modal-content</span> &#123;</span></span><br><span class="line">    margin: auto;</span><br><span class="line">    display: block;</span><br><span class="line">    width: 80%;</span><br><span class="line">    max-width: 700px;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* Caption of Modal Image */</span></span></span><br><span class="line"><span class="css"><span class="selector-id">#caption</span> &#123;</span></span><br><span class="line">    margin: auto;</span><br><span class="line">    display: block;</span><br><span class="line">    width: 80%;</span><br><span class="line">    max-width: 700px;</span><br><span class="line">    text-align: center;</span><br><span class="line"><span class="css">    <span class="selector-tag">color</span>: <span class="selector-id">#ccc</span>;</span></span><br><span class="line">    padding: 10px 0;</span><br><span class="line">    height: 150px;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* Add Animation */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.modal-content</span>, <span class="selector-id">#caption</span> &#123;    </span></span><br><span class="line">    -webkit-animation-name: zoom;</span><br><span class="line"><span class="css">    <span class="selector-tag">-webkit-animation-duration</span>: 0<span class="selector-class">.6s</span>;</span></span><br><span class="line">    animation-name: zoom;</span><br><span class="line"><span class="css">    <span class="selector-tag">animation-duration</span>: 0<span class="selector-class">.6s</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@-webkit-keyframes</span> zoom &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">from</span> &#123;<span class="attribute">-webkit-transform</span>: <span class="built_in">scale</span>(<span class="number">0</span>)&#125; </span></span><br><span class="line"><span class="css">    <span class="selector-tag">to</span> &#123;<span class="attribute">-webkit-transform</span>: <span class="built_in">scale</span>(<span class="number">1</span>)&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@keyframes</span> zoom &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">from</span> &#123;<span class="attribute">transform</span>: <span class="built_in">scale</span>(<span class="number">0.1</span>)&#125; </span></span><br><span class="line"><span class="css">    <span class="selector-tag">to</span> &#123;<span class="attribute">transform</span>: <span class="built_in">scale</span>(<span class="number">1</span>)&#125;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* The Close Button */</span></span></span><br><span class="line"><span class="css"><span class="selector-class">.close</span> &#123;</span></span><br><span class="line">    position: absolute;</span><br><span class="line">    top: 15px;</span><br><span class="line">    right: 35px;</span><br><span class="line"><span class="css">    <span class="selector-tag">color</span>: <span class="selector-id">#f1f1f1</span>;</span></span><br><span class="line">    font-size: 40px;</span><br><span class="line">    font-weight: bold;</span><br><span class="line"><span class="css">    <span class="selector-tag">transition</span>: 0<span class="selector-class">.3s</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-class">.close</span><span class="selector-pseudo">:hover</span>,</span></span><br><span class="line"><span class="css"><span class="selector-class">.close</span><span class="selector-pseudo">:focus</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">color</span>: <span class="selector-id">#bbb</span>;</span></span><br><span class="line">    text-decoration: none;</span><br><span class="line">    cursor: pointer;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="comment">/* 100% Image Width on Smaller Screens */</span></span></span><br><span class="line"><span class="css"><span class="keyword">@media</span> <span class="keyword">only</span> screen <span class="keyword">and</span> (<span class="attribute">max-width:</span> <span class="number">700px</span>)&#123;</span></span><br><span class="line"><span class="css">    <span class="selector-class">.modal-content</span> &#123;</span></span><br><span class="line">        width: 100%;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>图片模态框<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>本实例演示了如何结合 CSS 和 JavaScript 来一起渲染图片。<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">首先，我们使用 CSS 来创建 modal 窗口 (对话框), 默认是隐藏的。<span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>然后，我们使用 JavaScript 来显示模态窗口，当我们点击图片时，图片会在弹出的窗口中显示：<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">id</span>=<span class="string">"myImg"</span> <span class="attr">src</span>=<span class="string">"//www.runoob.com/wp-content/uploads/2016/04/img_lights.jpg"</span> <span class="attr">alt</span>=<span class="string">"Northern Lights, Norway"</span> <span class="attr">width</span>=<span class="string">"300"</span> <span class="attr">height</span>=<span class="string">"200"</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- The Modal --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"myModal"</span> <span class="attr">class</span>=<span class="string">"modal"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">"close"</span>&gt;</span>×<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">"modal-content"</span> <span class="attr">id</span>=<span class="string">"img01"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"caption"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript"><span class="comment">// 获取模态窗口</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> modal = <span class="built_in">document</span>.getElementById(<span class="string">'myModal'</span>);</span></span><br><span class="line"></span><br><span class="line"><span class="actionscript"><span class="comment">// 获取图片模态框，alt 属性作为图片弹出中文本描述</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> img = <span class="built_in">document</span>.getElementById(<span class="string">'myImg'</span>);</span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> modalImg = <span class="built_in">document</span>.getElementById(<span class="string">"img01"</span>);</span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> captionText = <span class="built_in">document</span>.getElementById(<span class="string">"caption"</span>);</span></span><br><span class="line"><span class="actionscript">img.onclick = <span class="function"><span class="keyword">function</span><span class="params">()</span></span>&#123;</span></span><br><span class="line"><span class="actionscript">    modal.style.display = <span class="string">"block"</span>;</span></span><br><span class="line"><span class="actionscript">    modalImg.src = <span class="keyword">this</span>.src;</span></span><br><span class="line"><span class="actionscript">    modalImg.alt = <span class="keyword">this</span>.alt;</span></span><br><span class="line"><span class="actionscript">    captionText.innerHTML = <span class="keyword">this</span>.alt;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="actionscript"><span class="comment">// 获取 &lt;span&gt; 元素，设置关闭模态框按钮</span></span></span><br><span class="line"><span class="javascript"><span class="keyword">var</span> span = <span class="built_in">document</span>.getElementsByClassName(<span class="string">"close"</span>)[<span class="number">0</span>];</span></span><br><span class="line"></span><br><span class="line"><span class="actionscript"><span class="comment">// 点击 &lt;span&gt; 元素上的 (x), 关闭模态框</span></span></span><br><span class="line"><span class="actionscript">span.onclick = <span class="function"><span class="keyword">function</span><span class="params">()</span> </span>&#123; </span></span><br><span class="line"><span class="actionscript">    modal.style.display = <span class="string">"none"</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="5、CSS3按钮"><a href="#5、CSS3按钮" class="headerlink" title="5、CSS3按钮"></a>5、CSS3按钮</h4><p>back-ground属性设置颜色；font-size属性设置大小；border-radius属性设置圆角按钮；border属性设置边框颜色；:hover选择器来修改鼠标悬停在按钮上的样式，并用transition-duration属性来设置hover效果的速度；box-shadow属性为按钮添加阴影；opacity属性添加透明度，看上去类似禁用的效果。</p>
<p>按钮动画：1、鼠标移动时添加箭头标记；</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-class">.button</span> &#123;</span></span><br><span class="line">  display: inline-block;</span><br><span class="line">  border-radius: 4px;</span><br><span class="line"><span class="css">  <span class="selector-tag">background-color</span>: <span class="selector-id">#f4511e</span>;</span></span><br><span class="line">  border: none;</span><br><span class="line"><span class="css">  <span class="selector-tag">color</span>: <span class="selector-id">#FFFFFF</span>;</span></span><br><span class="line">  text-align: center;</span><br><span class="line">  font-size: 28px;</span><br><span class="line">  padding: 20px;</span><br><span class="line">  width: 200px;</span><br><span class="line"><span class="css">  <span class="selector-tag">transition</span>: <span class="selector-tag">all</span> 0<span class="selector-class">.5s</span>;</span></span><br><span class="line">  cursor: pointer;</span><br><span class="line">  margin: 5px;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-class">.button</span> <span class="selector-tag">span</span> &#123;</span></span><br><span class="line">  cursor: pointer;</span><br><span class="line">  display: inline-block;</span><br><span class="line">  position: relative;</span><br><span class="line"><span class="css">  <span class="selector-tag">transition</span>: 0<span class="selector-class">.5s</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-class">.button</span> <span class="selector-tag">span</span><span class="selector-pseudo">:after</span> &#123;</span></span><br><span class="line">  content: '»';</span><br><span class="line">  position: absolute;</span><br><span class="line">  opacity: 0;</span><br><span class="line">  top: 0;</span><br><span class="line">  right: -20px;</span><br><span class="line"><span class="css">  <span class="selector-tag">transition</span>: 0<span class="selector-class">.5s</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-class">.button</span><span class="selector-pseudo">:hover</span> <span class="selector-tag">span</span> &#123;</span></span><br><span class="line">  padding-right: 25px;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-class">.button</span><span class="selector-pseudo">:hover</span> <span class="selector-tag">span</span><span class="selector-pseudo">:after</span> &#123;</span></span><br><span class="line">  opacity: 1;</span><br><span class="line">  right: 0;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>按钮动画<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">"button"</span> <span class="attr">style</span>=<span class="string">"vertical-align:middle"</span>&gt;</span><span class="tag">&lt;<span class="name">span</span>&gt;</span>Hover <span class="tag">&lt;/<span class="name">span</span>&gt;</span><span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>2、点击时添加压下效果：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-class">.button</span> &#123;</span></span><br><span class="line">  display: inline-block;</span><br><span class="line">  padding: 15px 25px;</span><br><span class="line">  font-size: 24px;</span><br><span class="line">  cursor: pointer;</span><br><span class="line">  text-align: center;   </span><br><span class="line">  text-decoration: none;</span><br><span class="line">  outline: none;</span><br><span class="line"><span class="css">  <span class="selector-tag">color</span>: <span class="selector-id">#fff</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">background-color</span>: <span class="selector-id">#4CAF50</span>;</span></span><br><span class="line">  border: none;</span><br><span class="line">  border-radius: 15px;</span><br><span class="line"><span class="css">  <span class="selector-tag">box-shadow</span>: 0 9<span class="selector-tag">px</span> <span class="selector-id">#999</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-class">.button</span><span class="selector-pseudo">:hover</span> &#123;<span class="attribute">background-color</span>: <span class="number">#3e8e41</span>&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-class">.button</span><span class="selector-pseudo">:active</span> &#123;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">background-color</span>: <span class="selector-id">#3e8e41</span>;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">box-shadow</span>: 0 5<span class="selector-tag">px</span> <span class="selector-id">#666</span>;</span></span><br><span class="line">  transform: translateY(4px);</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>按钮动画 - "按压效果"<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span> <span class="attr">class</span>=<span class="string">"button"</span>&gt;</span>Click Me<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="6、CSS分页"><a href="#6、CSS分页" class="headerlink" title="6、CSS分页"></a>6、CSS分页</h4><p>当网站有很多个页面时，需要使用分页来为每个页面做导航，以下实例演示如何用HTML和CSS来创建分页。</p>
<p>1、用.active来设置当前页样式，且鼠标悬停可用:hover选择器来修改样式；</p>
<p>2、用border-radius来为选中的页码添加圆角样式，添加transition属性添加鼠标移动到页码上时的过渡效果，border属性来添加带边框分页；</p>
<p>3、margin属性为每个页码间添加空格，font-size属性设置分页的字体大小，在容器元素上添加text-align:center样式实现分页居中。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-tag">ul</span><span class="selector-class">.pagination</span> &#123;</span></span><br><span class="line">    display: inline-block;</span><br><span class="line">    padding: 0;</span><br><span class="line">    margin: 0;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">ul</span><span class="selector-class">.pagination</span> <span class="selector-tag">li</span> &#123;<span class="attribute">display</span>: inline;&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">ul</span><span class="selector-class">.pagination</span> <span class="selector-tag">li</span> <span class="selector-tag">a</span> &#123;</span></span><br><span class="line">    color: black;</span><br><span class="line">    float: left;</span><br><span class="line">    padding: 8px 16px;</span><br><span class="line">    text-decoration: none;</span><br><span class="line"><span class="css">    <span class="selector-tag">transition</span>: <span class="selector-tag">background-color</span> <span class="selector-class">.3s</span>;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">border</span>: 1<span class="selector-tag">px</span> <span class="selector-tag">solid</span> <span class="selector-id">#ddd</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">ul</span><span class="selector-class">.pagination</span> <span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-class">.active</span> &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">background-color</span>: <span class="selector-id">#4CAF50</span>;</span></span><br><span class="line">    color: white;</span><br><span class="line"><span class="css">    <span class="selector-tag">border</span>: 1<span class="selector-tag">px</span> <span class="selector-tag">solid</span> <span class="selector-id">#4CAF50</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">ul</span><span class="selector-class">.pagination</span> <span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">:not(.active)</span> &#123;<span class="attribute">background-color</span>: <span class="number">#ddd</span>;&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-tag">div</span><span class="selector-class">.center</span> &#123;<span class="attribute">text-align</span>: center;&#125;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>分页居中<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"center"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">"pagination"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>«<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>1<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">"active"</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>2<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>3<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>4<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>5<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>6<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>7<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"#"</span>&gt;</span>»<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="7、CSS框大小设置"><a href="#7、CSS框大小设置" class="headerlink" title="7、CSS框大小设置"></a>7、CSS框大小设置</h4><p>CSS3中box-sizing属性可以设置width和height中，包含了padding（内边距）和border（边框）；</p>
<p>1、不使用box-sizing属性时，高 = height + border + padding；宽 = width + padding + border。高度、宽度设置一样时，真实展示大小不一定一样，因为指定的padding不同。</p>
<p>2、使用box-sizing时，该属性同时包括内边框与边框，其实这样效果更好，在元素上添加box-sizing:border-box的简单实例。</p>
<h4 id="8、CSS3弹性盒子"><a href="#8、CSS3弹性盒子" class="headerlink" title="8、CSS3弹性盒子"></a>8、CSS3弹性盒子</h4><p>Flex Box是一种新的布局模式，当页面需要适应不同的屏幕大小以及设备类型时，确保元素拥有恰当的行为的布局方式，提供flexbox的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间。</p>
<p>由弹性容器container和弹性子元素item组成，弹性容器通过设置display值为flex,将其定义为弹性容器。弹性容器外及弹性子元素内是正常渲染的。弹性盒子只定义了弹性子元素如何在弹性容器内布局。</p>
<p>弹性子元素通常在弹性盒子内一行显示。默认情况每个容器只有一行。以下元素展示了弹性子元素在一行内显示，从左到右:</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span> </span><br><span class="line"><span class="css"><span class="selector-class">.flex-container</span> &#123;</span></span><br><span class="line">    display: -webkit-flex;</span><br><span class="line">    display: flex;</span><br><span class="line">    width: 400px;</span><br><span class="line">    height: 250px;</span><br><span class="line">    background-color: lightgrey;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="selector-class">.flex-item</span> &#123;</span></span><br><span class="line">    background-color: cornflowerblue;</span><br><span class="line">    width: 100px;</span><br><span class="line">    height: 100px;</span><br><span class="line">    margin: 10px;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"flex-container"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"flex-item"</span>&gt;</span>flex item 1<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"flex-item"</span>&gt;</span>flex item 2<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"flex-item"</span>&gt;</span>flex item 3<span class="tag">&lt;/<span class="name">div</span>&gt;</span>  </span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>justify-content内容对齐属性应用在弹性容器上，把弹性项沿着容器的主轴线对齐；justify-content: flex-start | flex-end | center | space-between | space-around</p>
<p><code>align-items</code> 设置或检索弹性盒子元素在侧轴（纵轴）方向上的对齐方式。align-items: flex-start | flex-end | center | baseline | stretch</p>
<p><strong>flex-wrap</strong> 属性用于指定弹性盒子的子元素换行方式;flex-wrap: nowrap|wrap|wrap-reverse|initial|inherit;</p>
<p><code>align-content</code> 属性用于修改 <code>flex-wrap</code> 属性的行为。类似于 <code>align-items</code>, 但它不是设置弹性子元素的对齐，而是设置各个行的对齐。align-content: flex-start | flex-end | center | space-between | space-around | stretch</p>
<p>弹性子元素的属性：</p>
<p>1、排序：order；用整数值来定义排列顺序，数值小的排在前面。可以为负值</p>
<p>2、对齐：margin；设置”margin”值为”auto”值，自动获取弹性容器中剩余的空间。所以设置垂直方向margin值为”auto”，可以使弹性子元素在弹性容器的两上轴方向都完全居中。</p>
<p>3、<code>align-self</code> 属性用于设置弹性元素自身在侧轴（纵轴）方向上的对齐方式。align-self: auto | flex-start | flex-end | center | baseline | stretch</p>
<p>4、<code>flex</code> 属性用于指定弹性子元素如何分配空间。flex: auto | initial | none | inherit |  [ flex-grow ] || [ flex-shrink ] || [ flex-basis ]</p>
<h4 id="9、CSS3多媒体查询"><a href="#9、CSS3多媒体查询" class="headerlink" title="9、CSS3多媒体查询"></a>9、CSS3多媒体查询</h4><p>@media：CSS3的多媒体查询继承了CSS2中所有思想：取代了查找设备的类型，根据设置自适应显示。</p>
<p>多媒体查询由多种媒体组成，可以包含一个或多个表达式，表达式根据条件是否成立返回 true 或 false。</p>
<p>@media not|only mediatype and (expressions) {    CSS 代码…; }</p>
<p>如果指定的多媒体类型匹配设备类型则查询结果返回 true，文档会在匹配的设备上显示指定样式效果。除非你使用了 not 或 only 操作符，否则所有的样式会适应在所有设备上显示效果。</p>
<p>not是用来排除掉某些特定的设备的，比如 @media not print（非打印设备）。</p>
<p>only: 用来定某种特别的媒体类型。对于支持Media Queries的移动设备来说，如果存在only关键字，移动设备的Web浏览器会忽略only关键字并直接根据后面的表达式应用样式文件。对于不支持Media Queries的设备但能够读取Media Type类型的Web浏览器，遇到only关键字时会忽略这个样式文件。</p>
<p>all:所有设备，这个应该经常看到。</p>
<p>以下实例在屏幕可视窗口尺寸小于 600 像素时将 div 元素隐藏：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"viewport"</span> <span class="attr">content</span>=<span class="string">"width=device-width, initial-scale=1"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-tag">div</span><span class="selector-class">.example</span> &#123;</span></span><br><span class="line">  background-color: yellow;</span><br><span class="line">  padding: 20px;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width:</span> <span class="number">600px</span>) &#123;</span></span><br><span class="line"><span class="css">  <span class="selector-tag">div</span><span class="selector-class">.example</span> &#123;</span></span><br><span class="line">    display: none;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">h2</span>&gt;</span>屏幕可视尺寸小于 600 px 时，隐藏以下元素。<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"example"</span>&gt;</span>我是会隐藏的元素。<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>重置浏览器大小，查看效果。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>实例：制作一个电子邮箱的链接列表，注意 <code>data-email</code> 属性。在 HTML 中我们可以使用带 <code>data-</code> 前缀的属性来存储信息。当浏览器的宽度在 520 到 699px, 邮箱链接前添加邮件图标；当浏览器的宽度在 700 到 1000px, 会在邮箱链接前添加 “Email”；当浏览器的宽度大于 1001px 时，会在链接后添加邮件地址。我们会使用 <code>data-</code> 属性来为每个人名后添加邮件地址：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span><br><span class="line">ul &#123;</span><br><span class="line">    list-style-type: none;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ul li a &#123;</span><br><span class="line">    color: green;</span><br><span class="line">    text-decoration: none;</span><br><span class="line">    padding: 3px; </span><br><span class="line">    display: block;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width:</span> <span class="number">699px</span>) <span class="keyword">and</span> (<span class="attribute">min-width:</span> <span class="number">520px</span>), (<span class="attribute">min-width:</span> <span class="number">1151px</span>) &#123;</span></span><br><span class="line">    ul li a &#123;</span><br><span class="line">        padding-left: 30px;</span><br><span class="line"><span class="css">        <span class="selector-tag">background</span>: <span class="selector-tag">url</span>(<span class="selector-tag">email-icon</span><span class="selector-class">.png</span>) <span class="selector-tag">left</span> <span class="selector-tag">center</span> <span class="selector-tag">no-repeat</span>;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width:</span> <span class="number">1000px</span>) <span class="keyword">and</span> (<span class="attribute">min-width:</span> <span class="number">700px</span>) &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">ul</span> <span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-pseudo">:before</span> &#123;</span></span><br><span class="line">        content: "Email: ";</span><br><span class="line">        font-style: italic;</span><br><span class="line"><span class="css">        <span class="selector-tag">color</span>: <span class="selector-id">#666666</span>;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="css"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width:</span> <span class="number">1001px</span>) &#123;</span></span><br><span class="line"><span class="css">    <span class="selector-tag">ul</span> <span class="selector-tag">li</span> <span class="selector-tag">a</span><span class="selector-pseudo">:after</span> &#123;</span></span><br><span class="line">        content: " (" attr(data-email) ")";</span><br><span class="line">        font-size: 12px;</span><br><span class="line">        font-style: italic;</span><br><span class="line"><span class="css">        <span class="selector-tag">color</span>: <span class="selector-id">#666666</span>;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>重置浏览器窗口，查看效果!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">data-email</span>=<span class="string">"johndoe@example.com"</span> <span class="attr">href</span>=<span class="string">"mailto:johndoe@example.com"</span>&gt;</span>John Doe<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">data-email</span>=<span class="string">"marymoe@example.com"</span> <span class="attr">href</span>=<span class="string">"mailto:marymoe@example.com"</span>&gt;</span>Mary Moe<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">data-email</span>=<span class="string">"amandapanda@example.com"</span> <span class="attr">href</span>=<span class="string">"mailto:amandapanda@example.com"</span>&gt;</span>Amanda Panda<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>


      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/09/02/%E5%89%8D%E7%AB%AF/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/09/02/%E5%89%8D%E7%AB%AF/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/" class="post-title-link" itemprop="url">html</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-09-02 11:17:52" itemprop="dateCreated datePublished" datetime="2020-09-02T11:17:52+08:00">2020-09-02</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:25:32" itemprop="dateModified" datetime="2021-11-03T16:25:32+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E5%89%8D%E7%AB%AF%E9%A1%B5%E9%9D%A2/" itemprop="url" rel="index"><span itemprop="name">前端页面</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <p>使用堆的数据结构来对数组进行排序，找出第k大的数据，时间复杂度为O(n)</p>
<p>堆（英语：heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质：</p>
<ul>
<li>堆中某个节点的值总是不大于或不小于其父节点的值；</li>
<li>堆总是一棵完全二叉树。</li>
</ul>
<p>将根节点最大的堆叫做最大堆或大根堆，根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。</p>
<p>堆是非线性数据结构，相当于一维数组，有两个直接后继。</p>
<h2 id="1、基础知识"><a href="#1、基础知识" class="headerlink" title="1、基础知识"></a>1、基础知识</h2><p>可视化的html页面结构中，只有&lt; body &gt;区域才会在浏览器中显示。</p>
<p>目前在大部分浏览器中，直接输出中文会出现中文乱码的情况，需要在头部将字符声明为UTF-8或GBK。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="html元素语法："><a href="#html元素语法：" class="headerlink" title="html元素语法："></a>html元素语法：</h3><p>1、HTML元素以开始标签起始，以结束标签终止；2、元素的内容是开始标签与结束标签之间的内容；3、某些HTML元素具有空内容，空内容在开始标签中进行关闭，以开始标签的结束而结束；4、大多数HTML可拥有属性</p>
<h3 id="嵌套的HTML元素"><a href="#嵌套的HTML元素" class="headerlink" title="嵌套的HTML元素"></a>嵌套的HTML元素</h3><p>大多数HTML元素可以嵌套，HTML元素可包含其他HTML元素，且HTML文档由相互嵌套的HTML元素组成。</p>
<p>通常不要忘了用结束标签，虽然可以正确显示，但忘记使用结束标签往往会产生不可预料的结果或错误。</p>
<p>HTML标签对大小写不敏感，请一般使用小写标签。</p>
<h3 id="HTML属性"><a href="#HTML属性" class="headerlink" title="HTML属性"></a>HTML属性</h3><p>元素可设置属性；属性可以在元素中添加附加信息；属性一般描述于开始标签；属性总是以名称、值对的形式出现。比如：name=”value”。</p>
<p>HTML链接由&lt; a &gt;标签定义，链接地址在href属性中指定。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"http://www.runoob.com"</span>&gt;</span>这是一个链接<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="HTML格式"><a href="#HTML格式" class="headerlink" title="HTML格式"></a>HTML格式</h3><p>&lt; hr &gt;标签在HTML页面中创建水平线，用于分隔内容；</p>
<p>HTML注释：在开始括号之后紧跟一个叹号，结束括号前不需要</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 这是一个注释 --&gt;</span></span><br></pre></td></tr></table></figure>

<p>&lt; br &gt;使用br标签：在不产生一个新段落的情况下进行换行；</p>
<p>&lt; p &gt;定义一个段落</p>
<p>HTML使用标签&lt; b &gt;与&lt; i &gt;对输出的文本进行格式</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">b</span>&gt;</span>加粗文本<span class="tag">&lt;/<span class="name">b</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">i</span>&gt;</span>斜体文本<span class="tag">&lt;/<span class="name">i</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">code</span>&gt;</span>电脑自动输出<span class="tag">&lt;/<span class="name">code</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line">这是 <span class="tag">&lt;<span class="name">sub</span>&gt;</span> 下标<span class="tag">&lt;/<span class="name">sub</span>&gt;</span> 和 <span class="tag">&lt;<span class="name">sup</span>&gt;</span> 上标<span class="tag">&lt;/<span class="name">sup</span>&gt;</span></span><br></pre></td></tr></table></figure>



<p>HTML链接由&lt; a &gt;标签定义，链接地址在href属性中指定。</p>
<p>target属性：定义被链接的文档在何处显示；id属性：创建一个在HTML文档书签的标记；</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"http://www.runoob.com"</span>&gt;</span>这是一个链接<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="HTML头部"><a href="#HTML头部" class="headerlink" title="HTML头部"></a>HTML头部</h3><p>&lt; head &gt;元素包含了所有的头部标签元素，可以插入脚本、CSS（样式文件）以及各种meta信息</p>
<p>&lt; title &gt; 定义不同文档的标题；</p>
<p>&lt; base &gt; 描述了基本的链接地址、链接目标，作为默认链接；</p>
<p>&lt; link &gt; 定义了文档与外部资源之间的关系，用于链接到样式表；</p>
<p>&lt; style &gt;元素：定义了HTML文档的样式文件引用地址，在该元素中直接添加样式来渲染HTML；</p>
<p>&lt; meta &gt;元素：描述了一些基本的元数据，通常用于指定网页的描述，关键词，文件最后的修改时间，作者和其他元数据。</p>
<p>&lt; script &gt; 用于加载脚本文件，如javascript</p>
<h3 id="HTML样式-CSS"><a href="#HTML样式-CSS" class="headerlink" title="HTML样式 CSS"></a>HTML样式 CSS</h3><p>用于渲染HTML元素标签的样式，三种方式添加到HTML中：1、内联样式：在HTML元素中使用style属性；2、内部样式表：在HTML文档头部使用&lt; style &gt; 来包含CSS；3、外部引用：使用外部CSS文件。</p>
<p>最好的方式是外部引用；当特殊的样式需要应用到个别元素时，就可以使用内联样式，在相关标签中使用样式属性。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">h1</span> <span class="attr">style</span>=<span class="string">"font-family:verdana;"</span>&gt;</span>一个标题<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">style</span>=<span class="string">"font-family:arial;color:red;font-size:20px;"</span>&gt;</span>一个段落。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>内部样式表：当单个文件需要特别样式时，在&lt; head &gt;部分通过&lt; style &gt;标签定义。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">"text/css"</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-tag">body</span> &#123;<span class="attribute">background-color</span>:yellow;&#125;</span></span><br><span class="line"><span class="css"><span class="selector-tag">p</span> &#123;<span class="attribute">color</span>:blue;&#125;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>当样式被应用到很多页面时，外部样式表是理想选择，使用外部样式表，可以通过更改一个文件来修改一整个站点的外观。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">type</span>=<span class="string">"text/css"</span> <span class="attr">href</span>=<span class="string">"mystyle.css"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="HTML图像"><a href="#HTML图像" class="headerlink" title="HTML图像"></a>HTML图像</h3><p>图像由&lt; img &gt; 标签定义，为空标签，只有属性而无闭合标签，可使用源属性src，其值是图像的URL地址。alt属性用来为图像定义一串预备的可替换文本，在浏览器无法载入图像时，替换文本告诉读者他们失去的信息。</p>
<p>height、width属性用于设置图像的高度与宽度；</p>
<h3 id="HTML表格"><a href="#HTML表格" class="headerlink" title="HTML表格"></a>HTML表格</h3><p>表格由&lt; table &gt;标签来定义，每个表格有若干行（由&lt; tr &gt;标签定义），每行被分割为若干单元格（由&lt; td &gt;标签定义），td指表格数据即数据单元格的内容，border属性来定义表格的边框。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">table</span> <span class="attr">border</span>=<span class="string">"1"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>row 1, cell 1<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>row 1, cell 2<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>row 2, cell 1<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>row 2, cell 2<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">table</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="HTML列表"><a href="#HTML列表" class="headerlink" title="HTML列表"></a>HTML列表</h3><p>无序列表用&lt; ul &gt;标签</p>
<p>有序列表始于&lt; ol &gt;标签，每个列表项始于&lt; li &gt;标签，且列表各项会自动使用数字来标记。</p>
<p>自定义列表：项目及其注释的组合；以&lt; dl &gt;标签开始，每个自定义列表项从&lt; dt &gt;开始，每个自定义列表的定义以 &lt; dd &gt;开始。</p>
<h3 id="HTML区块"><a href="#HTML区块" class="headerlink" title="HTML区块"></a>HTML区块</h3><p>可通过 &lt; div &gt;和&lt; span &gt;将元素组合起来</p>
<p>大多数HTML元素被定义为块级元素、内联元素；块级元素，通常以新行开始和结束，内联元素：显示时不会以新行开始；</p>
<p>&lt; div &gt;元素是块级元素，可用于组合其他元素的容器，无特定含义，与CSS一同使用时，可用于对大的内容块设置样式属性；&lt; div &gt;元素的另一个常见作用是文档布局，用table显示表格化数据，用div进行表格定义布局。</p>
<p>&lt; span &gt;元素是内联元素，可用作文本的容器</p>
<h3 id="HTML布局"><a href="#HTML布局" class="headerlink" title="HTML布局"></a>HTML布局</h3><p>使用div、table元素来创建多列，CSS用于元素定位或为页面创建背景以及色彩丰富的外观。</p>
<p>使用CSS最大的好处是，如果将带啊存放到外部样式表中，那么站点更易于维护，通过编辑单一的文件就可以改变所有页面的布局。</p>
<h3 id="HTML表单"><a href="#HTML表单" class="headerlink" title="HTML表单"></a>HTML表单</h3><p>用于收集不同类型的用户输入，表单是一个包含表单元素的区域，表单元素允许用户在表单中输入内容，表单标签用&lt; form &gt;来设置。</p>
<p>输入元素input，输入类型由类型属性type定义。text：文本域；password：密码字段；radio：单选按钮；checkbox：复选框；submit：提交按钮</p>
<h3 id="HTML框架、"><a href="#HTML框架、" class="headerlink" title="HTML框架、"></a>HTML框架、</h3><p>通过使用框架可以在同一个浏览器窗口显示不止一个页面；</p>
<p>iframe语法：&lt; iframe src=”URL” &gt;&lt; /iframe &gt;</p>
<p>使用height、width来设置高宽，frameborder属性用于定义iframe表示是否显示边框</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">iframe</span> <span class="attr">src</span>=<span class="string">"demo_iframe.htm"</span> <span class="attr">name</span>=<span class="string">"iframe_a"</span>&gt;</span><span class="tag">&lt;/<span class="name">iframe</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"//www.runoob.com"</span> <span class="attr">target</span>=<span class="string">"iframe_a"</span>&gt;</span>RUNOOB.COM<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>注意：<span class="tag">&lt;/<span class="name">b</span>&gt;</span> 因为 a 标签的 target 属性是名为 iframe_a 的 iframe 框架，所以在点击链接时页面会显示在 iframe框架中。<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>因为 a 标签的 target 属性是名为 iframe_a 的 iframe 框架，所以在点击链接时页面会显示在 iframe框架中</p>
<h3 id="HTML颜色"><a href="#HTML颜色" class="headerlink" title="HTML颜色"></a>HTML颜色</h3><p>由16进制符号来定义，RGB三向通道，FF FF FF</p>
<p>141个颜色名称是在HTML和CSS颜色规范定义的，17中表针颜色，124种非标准。</p>
<h3 id="HTML脚本"><a href="#HTML脚本" class="headerlink" title="HTML脚本"></a>HTML脚本</h3><p>script标签用于定义客户端脚本，比如JavaScript，script元素即可包含脚本语句，也可以通过src属性指向外部脚本文件。JavaScript最常用与图片操作、表单验证以及内容·动态更新。</p>
<p>noscript提供无法使用脚本时的替代内容，可包含普通HTML页面的body元素中能够找到的所有元素。</p>
<h3 id="HTML字符实体"><a href="#HTML字符实体" class="headerlink" title="HTML字符实体"></a>HTML字符实体</h3><p>其中，某些字符是预留的，比如&gt; 、&lt;；因此需要在源代码中使用字符实体；常用字符实体是不间断空格&amp;nbsp，由于浏览器总会截断HTML页面的空格，只留下一个，因此如果需要在页面中增加空格数量，需要用到&amp;nbsp。</p>
<p>字符实体的名称对大小写敏感。</p>
<h3 id="HTML-URL"><a href="#HTML-URL" class="headerlink" title="HTML URL"></a>HTML URL</h3><p>URL是一个网页地址，Web浏览器通过URL从Web服务器请求页面，当点击页面上链接时，对应标签指向万维网上地址。</p>
<p>一个网页地址实例: <a href="http://www.runoob.com/html/html-tutorial.html" target="_blank" rel="noopener">http://www.runoob.com/html/html-tutorial.html</a> 语法规则:</p>
<p><strong>scheme<code>://</code>host.domain<code>:</code>port<code>/</code>path<code>/</code>filename</strong></p>
<p>说明:</p>
<ul>
<li><ul>
<li>scheme - 定义因特网服务的类型。最常见的类型是 http</li>
<li>host - 定义域主机（http 的默认主机是 www）</li>
<li>domain - 定义因特网域名，比如 runoob.com</li>
<li>:port - 定义主机上的端口号（http 的默认端口号是 80）</li>
<li>path - 定义服务器上的路径（如果省略，则文档必须位于网站的根目录中）。</li>
<li>filename - 定义文档/资源的名称</li>
</ul>
</li>
</ul>
<p>http：超文本传输协议；https:安全超文本传输协议；ftp：文件传输协议；file：自己计算机上文件。</p>
<p>URL 只能使用 <a href="https://www.runoob.com/tags/html-ascii.html" target="_blank" rel="noopener">ASCII 字符集</a>.</p>
<p>来通过因特网进行发送。由于 URL 常常会包含 ASCII 集合之外的字符，URL 必须转换为有效的 ASCII 格式。</p>
<p>URL 编码使用 “%” 其后跟随两位的十六进制数来替换非 ASCII 字符。</p>
<p>URL 不能包含空格。URL 编码通常使用 + 来替换空格。</p>
<h3 id="HTML速查列表"><a href="#HTML速查列表" class="headerlink" title="HTML速查列表"></a>HTML速查列表</h3><p><img src="/../../image/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/%E9%80%9F%E6%9F%A5%E5%88%97%E8%A1%A81.png" alt="速查列表1"></p>
<p><img src="/../../image/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/%E9%80%9F%E6%9F%A5%E5%88%97%E8%A1%A82.png" alt="速查列表2"></p>
<p><img src="/../../image/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/%E9%80%9F%E6%9F%A5%E5%88%97%E8%A1%A83.png" alt="速查列表3"></p>
<p><img src="/../../image/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/%E9%80%9F%E6%9F%A5%E5%88%97%E8%A1%A84.png" alt="速查列表4"></p>
<p><img src="/../../image/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/%E9%80%9F%E6%9F%A5%E5%88%97%E8%A1%A85.png" alt="速查列表5"></p>
<p><img src="/../../image/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/%E9%80%9F%E6%9F%A5%E5%88%97%E8%A1%A86.png" alt="速查列表6"></p>
<h2 id="2、H5前端开发"><a href="#2、H5前端开发" class="headerlink" title="2、H5前端开发"></a>2、H5前端开发</h2><p>为了更好地处理今天的互联网应用，HTML5添加了很多新元素及功能，比如: 图形的绘制，多媒体内容，更好的页面结构，更好的形式 处理，和几个api拖放元素，定位，包括网页 应用程序缓存，存储，网络工作者，等。</p>
<h3 id="HTML5-Canvas"><a href="#HTML5-Canvas" class="headerlink" title="HTML5 Canvas"></a>HTML5 Canvas</h3><p>canvas标签定义图形，只是图形的容器，必须使用脚本来绘制图形。</p>
<p>一个画布在网页中是一个矩形框，通过canvas元素来绘制，指定id属性，height、width属性来定义画布大小，使用style属性来添加边框。</p>
<h3 id="H5内联SVG"><a href="#H5内联SVG" class="headerlink" title="H5内联SVG"></a>H5内联SVG</h3><p>SVG指可伸缩矢量图形，用于定义用于网络的基于矢量的图形；使用XML格式定义图形，SVG图像在放大或改变尺寸的情况下其图形质量不会有损失，SVG是万维网联盟的标准。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">svg</span> <span class="attr">xmlns</span>=<span class="string">"http://www.w3.org/2000/svg"</span> <span class="attr">version</span>=<span class="string">"1.1"</span> <span class="attr">height</span>=<span class="string">"190"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">polygon</span> <span class="attr">points</span>=<span class="string">"100,10 40,180 190,60 10,60 160,180"</span></span></span><br><span class="line"><span class="tag">  <span class="attr">style</span>=<span class="string">"fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">svg</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>SVG是一种使用XML描述2D图形的语言，而Canvas通过JavaScript绘制2D图形。</p>
<p>SVG基于XML，因此SVG DOM中的每个元素都是可用的，可以为某个元素附加JavaScript事件处理器，在SVG中，每个被绘制的图形均被视为对象，若SVG对象属性发生变化，那么浏览器能自动重现图形；</p>
<p>Canvas是逐像素进行渲染，一旦图形被绘制完成，便不会得到浏览器的关注，如果其位置发生变化，则整个场景需要进行重新绘制。</p>
<p><img src="/../../image/html%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/SVG%E4%B8%8ECanvas.png" alt="SVG与Canvas"></p>
<h3 id="HTML5-MathML"><a href="#HTML5-MathML" class="headerlink" title="HTML5  MathML"></a>HTML5  MathML</h3><p>标签math，MathML是数学标记语言，基于XML的标准，用于互联网上书写数学符号与公式。</p>
<h3 id="HTML5拖放drag和drop"><a href="#HTML5拖放drag和drop" class="headerlink" title="HTML5拖放drag和drop"></a>HTML5拖放drag和drop</h3><p>拖放是一种常见的特性，即抓取对象以后拖到另一个位置，在H5中任何元素都可以拖放。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">HTML</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">"text/css"</span>&gt;</span></span><br><span class="line"><span class="css"><span class="selector-id">#div1</span> &#123;<span class="attribute">width</span>:<span class="number">350px</span>;<span class="attribute">height</span>:<span class="number">70px</span>;<span class="attribute">padding</span>:<span class="number">10px</span>;<span class="attribute">border</span>:<span class="number">1px</span> solid <span class="number">#aaaaaa</span>;&#125;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="actionscript"><span class="function"><span class="keyword">function</span> <span class="title">allowDrop</span><span class="params">(ev)</span></span></span></span><br><span class="line">&#123;</span><br><span class="line">    ev.preventDefault();</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="actionscript"><span class="function"><span class="keyword">function</span> <span class="title">drag</span><span class="params">(ev)</span></span></span></span><br><span class="line">&#123;</span><br><span class="line"><span class="actionscript">    ev.dataTransfer.setData(<span class="string">"Text"</span>,ev.target.id);</span></span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="actionscript"><span class="function"><span class="keyword">function</span> <span class="title">drop</span><span class="params">(ev)</span></span></span></span><br><span class="line">&#123;</span><br><span class="line">    ev.preventDefault();</span><br><span class="line"><span class="actionscript">    <span class="keyword">var</span> data=ev.dataTransfer.getData(<span class="string">"Text"</span>);</span></span><br><span class="line"><span class="javascript">    ev.target.appendChild(<span class="built_in">document</span>.getElementById(data));</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>拖动 RUNOOB.COM 图片到矩形框中:<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"div1"</span> <span class="attr">ondrop</span>=<span class="string">"drop(event)"</span> <span class="attr">ondragover</span>=<span class="string">"allowDrop(event)"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">br</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">id</span>=<span class="string">"drag1"</span> <span class="attr">src</span>=<span class="string">"/images/logo.png"</span> <span class="attr">draggable</span>=<span class="string">"true"</span> <span class="attr">ondragstart</span>=<span class="string">"drag(event)"</span> <span class="attr">width</span>=<span class="string">"336"</span> <span class="attr">height</span>=<span class="string">"69"</span>&gt;</span></span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>1、设置元素可拖放：把draggable属性设置为true；</p>
<p>2、拖动什么：ondragstart属性调用了一个函数drag(event)，并在函数中用dataTransfer.setData()方法设置被拖数据的数据类型和值；</p>
<p>3、放到何处：ondragover事件规定在何处放置被拖动的数据，默认中无法将数据、元素放置到其他元素中，通过调用ondragover事件的event.preventDefault()方法</p>
<p>4、进行放置：当放置被拖数据时，会发生drop事件，在上面的例子中ondrop属性调用了一个函数，drop(event)</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">function drop(ev)</span><br><span class="line">&#123;</span><br><span class="line">    ev.preventDefault();</span><br><span class="line">    var data=ev.dataTransfer.getData("Text");</span><br><span class="line">    ev.target.appendChild(document.getElementById(data));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>调用 preventDefault() 来避免浏览器对数据的默认处理（drop 事件的默认行为是以链接形式打开）</li>
<li>通过 dataTransfer.getData(“Text”) 方法获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据。</li>
<li>被拖数据是被拖元素的 id (“drag1”)</li>
<li>把被拖元素追加到放置元素（目标元素）中</li>
</ul>
<h3 id="H5地理定位"><a href="#H5地理定位" class="headerlink" title="H5地理定位"></a>H5地理定位</h3><h3 id="H5视频"><a href="#H5视频" class="headerlink" title="H5视频"></a>H5视频</h3><p>H5规定了一种通过video元素来包含视频的标准方法，</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">video</span> <span class="attr">width</span>=<span class="string">"320"</span> <span class="attr">height</span>=<span class="string">"240"</span> <span class="attr">controls</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">source</span> <span class="attr">src</span>=<span class="string">"movie.mp4"</span> <span class="attr">type</span>=<span class="string">"video/mp4"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">source</span> <span class="attr">src</span>=<span class="string">"movie.ogg"</span> <span class="attr">type</span>=<span class="string">"video/ogg"</span>&gt;</span></span><br><span class="line">您的浏览器不支持Video标签。</span><br><span class="line"><span class="tag">&lt;/<span class="name">video</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>video与audio元素同样拥有方法、属性、事件，且均可以使用JavaScript进行控制。方法：用于播放、暂停、加载；属性：时长、音量可以被读取或设置；其中DOM事件可以通知用户。下面的例子调用了play()和pause()方法，且使用了paused、width属性。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>菜鸟教程(runoob.com)<span class="tag">&lt;/<span class="name">title</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span> </span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">"text-align:center"</span>&gt;</span> </span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">"playPause()"</span>&gt;</span>播放/暂停<span class="tag">&lt;/<span class="name">button</span>&gt;</span> </span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">"makeBig()"</span>&gt;</span>放大<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">"makeSmall()"</span>&gt;</span>缩小<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">"makeNormal()"</span>&gt;</span>普通<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">br</span>&gt;</span> </span><br><span class="line">  <span class="tag">&lt;<span class="name">video</span> <span class="attr">id</span>=<span class="string">"video1"</span> <span class="attr">width</span>=<span class="string">"420"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">source</span> <span class="attr">src</span>=<span class="string">"mov_bbb.mp4"</span> <span class="attr">type</span>=<span class="string">"video/mp4"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">source</span> <span class="attr">src</span>=<span class="string">"mov_bbb.ogg"</span> <span class="attr">type</span>=<span class="string">"video/ogg"</span>&gt;</span></span><br><span class="line">    您的浏览器不支持 HTML5 video 标签。</span><br><span class="line">  <span class="tag">&lt;/<span class="name">video</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span> </span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span> </span><br><span class="line"><span class="javascript"><span class="keyword">var</span> myVideo=<span class="built_in">document</span>.getElementById(<span class="string">"video1"</span>); </span></span><br><span class="line"></span><br><span class="line"><span class="actionscript"><span class="function"><span class="keyword">function</span> <span class="title">playPause</span><span class="params">()</span></span></span></span><br><span class="line">&#123; </span><br><span class="line">	if (myVideo.paused) </span><br><span class="line">	  myVideo.play(); </span><br><span class="line"><span class="actionscript">	<span class="keyword">else</span> </span></span><br><span class="line">	  myVideo.pause(); </span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="actionscript">	<span class="function"><span class="keyword">function</span> <span class="title">makeBig</span><span class="params">()</span></span></span></span><br><span class="line">&#123; </span><br><span class="line">	myVideo.width=560; </span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="actionscript">	<span class="function"><span class="keyword">function</span> <span class="title">makeSmall</span><span class="params">()</span></span></span></span><br><span class="line">&#123; </span><br><span class="line">	myVideo.width=320; </span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="actionscript">	<span class="function"><span class="keyword">function</span> <span class="title">makeNormal</span><span class="params">()</span></span></span></span><br><span class="line">&#123; </span><br><span class="line">	myVideo.width=420; </span><br><span class="line">&#125; </span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span> </span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="H5新的Input类型"><a href="#H5新的Input类型" class="headerlink" title="H5新的Input类型"></a>H5新的Input类型</h3><p>color、data(从日期选择器中选择时间)、datetime、datetime-local、email、month、number、range（用于应该包含一定范围内数字值的输入域）、search（定义一个搜索字段）、tel、time、url（自动验证url域的值）、week、</p>
<h3 id="H5新的表单元素"><a href="#H5新的表单元素" class="headerlink" title="H5新的表单元素"></a>H5新的表单元素</h3><p>datalist：规定输入域的选项列表，该属性规定form、input域应该拥有自动完成功能，当用户在自动完成域中开始输入时，浏览器应该在该域中显示填写的选项，实现一个可输入下拉框的功能。</p>
<p>keygen：提供一种验证用户的可靠方法，规定用于表单的密钥生成器字段；当提交表单时，会生成2个键，一个为私钥、一个为公钥，私钥存储于客户端，公钥被发送至服务器，公钥可用于之后验证用户的客户端证书。</p>
<p>output元素：用于不同类型的输出</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">oninput</span>=<span class="string">"x.value=parseInt(a.value)+parseInt(b.value)"</span>&gt;</span>0</span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"range"</span> <span class="attr">id</span>=<span class="string">"a"</span> <span class="attr">value</span>=<span class="string">"50"</span>&gt;</span>100 +</span><br><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"number"</span> <span class="attr">id</span>=<span class="string">"b"</span> <span class="attr">value</span>=<span class="string">"50"</span>&gt;</span>=</span><br><span class="line"><span class="tag">&lt;<span class="name">output</span> <span class="attr">name</span>=<span class="string">"x"</span> <span class="attr">for</span>=<span class="string">"a b"</span>&gt;</span><span class="tag">&lt;/<span class="name">output</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="H5表单属性"><a href="#H5表单属性" class="headerlink" title="H5表单属性"></a>H5表单属性</h3><p>H5的form、input标签添加了几个新属性</p>
<form>新属性：

<ul>
<li>autocomplete</li>
<li>novalidate</li>
</ul>
<p><input>新属性：</p>
<ul>
<li>autocomplete</li>
<li>autofocus</li>
<li>form</li>
<li>formaction</li>
<li>formenctype</li>
<li>formmethod</li>
<li>formnovalidate</li>
<li>formtarget</li>
<li>height 与 width</li>
<li>list</li>
<li>min 与 max</li>
<li>multiple</li>
<li>pattern (regexp)</li>
<li>placeholder</li>
<li>required</li>
<li>step</li>
</ul>
<h3 id="H5语义元素"><a href="#H5语义元素" class="headerlink" title="H5语义元素"></a>H5语义元素</h3><p>语义元素：有意义的元素：能够清楚地描述其意义给浏览器和开发者；</p>
<p>H5提供了新的语义元素来明确一个Web页面的不同部分。</p>
<p>header（头部区域，定义内容的介绍展示区域）、nav(定义导航链接)、section（定义文档节，页眉、章节）、article（定义独立的内容）、aside（主区域以外的内容，如侧边栏）、figcaption、figure、footer（底部区域）</p>
<h3 id="H5的Web存储"><a href="#H5的Web存储" class="headerlink" title="H5的Web存储"></a>H5的Web存储</h3><p>在本地存储用户的浏览数据，数据以键值对存在，只允许该网页访问使用。</p>
<p>localStorage对象：用于长久保存整个网站的数据，保存数据无过期时间；</p>
<p>sessionStorage对象：用于临时保存同一窗口数据，在关闭窗口后会删除数据。</p>
<h3 id="H5-Web-SQL数据库"><a href="#H5-Web-SQL数据库" class="headerlink" title="H5 Web SQL数据库"></a>H5 Web SQL数据库</h3><p>引入了一组使用SQL操作客户端数据库的APIs，拥有三个核心方法：</p>
<p>1、openDatabase:使用现有的数据库创建一个数据库对象；</p>
<p>2、transaction：控制一个事务，以及基于这种情况执行提交或回滚；</p>
<p>3、executeSql：执行实际的SQL查询。</p>
<h3 id="H5-Web-Workers"><a href="#H5-Web-Workers" class="headerlink" title="H5 Web Workers"></a>H5 Web Workers</h3><p>web worker是运行在后台的JS，不会影响页面的性能，当HTML页面执行脚本时，页面的状态不可响应直至脚本完成，而Web Worker是运行在后台的JS，独立于其他脚本，不影响页面的性能，可继续做想做的事情。</p>
<h3 id="HTML5-WebSocket"><a href="#HTML5-WebSocket" class="headerlink" title="HTML5 WebSocket"></a>HTML5 WebSocket</h3><p>WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。</p>
<p>WebSocket 使得客户端和服务器之间的数据交换变得更加简单，允许服务端主动向客户端推送数据。在 WebSocket API 中，浏览器和服务器只需要完成一次握手，两者之间就直接可以创建持久性的连接，并进行双向数据传输。</p>
<p>在 WebSocket API 中，浏览器和服务器只需要做一个握手的动作，然后，浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。</p>
<p>现在，很多网站为了实现推送技术，所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔（如每1秒），由浏览器对服务器发出HTTP请求，然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点，即浏览器需要不断的向服务器发出请求，然而HTTP请求可能包含较长的头部，其中真正有效的数据可能只是很小的一部分，显然这样会浪费很多的带宽等资源。</p>
<p>HTML5 定义的 WebSocket 协议，能更好的节省服务器资源和带宽，并且能够更实时地进行通讯</p>

      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/08/29/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/08/29/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/" class="post-title-link" itemprop="url">自然语言处理</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-08-29 19:02:46" itemprop="dateCreated datePublished" datetime="2020-08-29T19:02:46+08:00">2020-08-29</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:23:47" itemprop="dateModified" datetime="2021-11-03T16:23:47+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/" itemprop="url" rel="index"><span itemprop="name">机器学习</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <h2 id="词嵌入"><a href="#词嵌入" class="headerlink" title="词嵌入"></a>词嵌入</h2><p>one-hot词向量构造起来很容易，但并不是一个含选择，因为其并不能准确地表达不同词之间的相似度，word2vec工具提出解决了上述问题，将每个词表示成一个定长的向量，并使这些向量能较好地表达不同词之间的相似和类比关系，包括跳字模型和连续词袋模型。</p>
<h3 id="跳字模型"><a href="#跳字模型" class="headerlink" title="跳字模型"></a>跳字模型</h3><p>跳字模型假设：基于某个词来生成它在文本序列周围的词。</p>
<p>在该模型中，每个词被分为2个d维向量，用来计算条件概率，假设该词在词典索引为i，当它为中心词时向量表示为Vi，而它为背景词时向量表示为Ui。</p>
<p>设中心词Wc在词典中索引为c，背景词Wo在词典中索引为o，故给定中心词生成背景词的条件概率可以通过对向量内积做softmax运算而得到：<img src="/../../image/%E8%87%AA%E7%84%B6%E8%AF%AD%E8%A8%80%E5%A4%84%E7%90%86/%E8%B7%B3%E5%AD%97%E6%A8%A1%E5%9E%8B%E6%9D%A1%E4%BB%B6%E6%A6%82%E7%8E%87.png" alt="跳字模型条件概率"></p>
<p>跳字模型的参数是每个词所对应的中心词向量和背景词向量，训练中一般使用最大似然函数来学习模型参数</p>
<h3 id="连续词袋模型"><a href="#连续词袋模型" class="headerlink" title="连续词袋模型"></a>连续词袋模型</h3><p>与跳字模型不同的是，连续词袋模型假设：基于某中心词在文本序列前后的背景词来生成该中心词。因为连续词袋模型的背景词有很多个，因此将这些取平均，然后使用和跳字模型一样的方法来计算条件概率。</p>
<p>同样，连续词袋模型的最大似然估计等价于最小化损失函数。</p>
<h3 id="近似训练"><a href="#近似训练" class="headerlink" title="近似训练"></a>近似训练</h3><p>跳字模型的核心在于，使用softmax运算得到给定中间词Wc生成背景词Wo的条件概率，，该条件概率对应的对数损失；</p>
<p>由于softmax运算考虑背景词可能是词典中任一词，以上损失包含了词典大小数目的项的累加。因此每次梯度计算可能开销过大，有下面两种方法来进行近似训练。</p>
<p>负采样：修改了原来的目标函数，使用相互独立事件来构造损失函数，其训练中每一步梯度计算开销与采样的噪声词的个数线性相关。</p>
<p>层序softmax：使用了二叉树这一个数据结构，树的每个叶结点代表词典中的每个词，并根据根节点到叶节点的路径来构造损失函数，每一步的梯度计算开销与词典大小的对数相关。</p>
<h2 id="word2vec的实现"><a href="#word2vec的实现" class="headerlink" title="word2vec的实现"></a>word2vec的实现</h2><h3 id="预处理数据集"><a href="#预处理数据集" class="headerlink" title="预处理数据集"></a>预处理数据集</h3><p>PTB是常用的语料库</p>
<p>1、建立词语索引：将词映射到整数索引</p>
<p>2、二次采样：：文本中一般会出现一些高频词，而在背景窗口中，与高频词一起出现会更有益。故训练词嵌入模型时可以对词进行二次采样，即每个索引词都有一定概率被丢弃。</p>
<p>3、提取中心词与背景词：我们将与中心词距离不超过背景窗口大小的词作为背景词，定义函数提取出所有中心词和它们的背景词。它每次在整数1与max_window_size之间随机均匀采样一个整数作为背景窗口大小。</p>
<h3 id="负采样"><a href="#负采样" class="headerlink" title="负采样"></a>负采样</h3><h3 id="读取数据集"><a href="#读取数据集" class="headerlink" title="读取数据集"></a>读取数据集</h3><p>使用随机小批量来读取数据集，小批量读取函数batchify，其输入data是一个长度为批量大小的列表，其中每个元素分别包含中心词center、背景词context、噪声词negativ，其返回的小批量数据符合我们需要的格式。</p>
<h3 id="跳字模型-1"><a href="#跳字模型-1" class="headerlink" title="跳字模型"></a>跳字模型</h3><p>嵌入层：获取词嵌入的层称为嵌入层，在Gluon中可以通过创建nn.Embedding实例得到。其权重为一个矩阵，行数为词典大小、列数为每个词向量的维度。嵌入层输入为词的索引，返回为权重矩阵的第i行作为它的词向量。</p>
<p>小批量乘法：batch_dot对两个小批量中的矩阵一一做乘法。</p>
<p>跳字模型前向计算：输入包含中心词索引center以及连结的背景词与噪声词索引contexts_and_negatives。</p>
<p>定义损失函数：使用Gluon的二元交叉熵函数</p>
<h2 id="子词嵌入fastText"><a href="#子词嵌入fastText" class="headerlink" title="子词嵌入fastText"></a>子词嵌入fastText</h2><p>英语单词通常由其内部结构和形成方式，而在word2vec中，我们并没有直接利用构词学中信息，而在fastText中，每个中心词被表示为子词的集合，利用</p>
<h2 id="全局向量的词嵌入GloVe"><a href="#全局向量的词嵌入GloVe" class="headerlink" title="全局向量的词嵌入GloVe"></a>全局向量的词嵌入GloVe</h2><h2 id="文本分类情感分析：使用循环神经网络"><a href="#文本分类情感分析：使用循环神经网络" class="headerlink" title="文本分类情感分析：使用循环神经网络"></a>文本分类情感分析：使用循环神经网络</h2><p>文本分类是自然语言处理的一个常见任务，将一段不定长的文本序列变换成文本的类别。</p>
<p>子问题：使用文本情感分析来分析文本作者的情绪，即情感分析。</p>
<h2 id="文本情感分析：使用卷积神经网络textCNN"><a href="#文本情感分析：使用卷积神经网络textCNN" class="headerlink" title="文本情感分析：使用卷积神经网络textCNN"></a>文本情感分析：使用卷积神经网络textCNN</h2><p>其实，我们也可以将文本看作一维图像，从而可以使用一维卷积神经网络来捕捉临近词之间的关联，</p>
<h2 id="编码器-解码器Seq2seq"><a href="#编码器-解码器Seq2seq" class="headerlink" title="编码器-解码器Seq2seq"></a>编码器-解码器Seq2seq</h2><p>前面都是表征并变换了不定长的输入序列，但在自然语言处理的很多应用中，输入、输出都可以是不定长序列，此时可用编码、解码器或Seq2seq模型。两个模型的本质都用到了两个循环神经网络，分别为编码器、解码器。+</p>

      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/08/28/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/08/28/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/" class="post-title-link" itemprop="url">计算机视觉</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-08-28 18:44:52" itemprop="dateCreated datePublished" datetime="2020-08-28T18:44:52+08:00">2020-08-28</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:23:31" itemprop="dateModified" datetime="2021-11-03T16:23:31+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/" itemprop="url" rel="index"><span itemprop="name">机器学习</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <p>在卷积神经网络中介绍了计算机视觉领域常用的深度学习模型，并实践了简单的图像分类。先描述目标检测的流程与方法，再使用全卷积网络对图像做语义分割，之后用样式迁移技术生成图像。</p>
<h2 id="图像增广"><a href="#图像增广" class="headerlink" title="图像增广"></a>图像增广</h2><p>1、扩大样本数据集；2、随机改变训练样本可降低模型对某些属性的依赖。两者均为了提高模型的泛化性。</p>
<p>常用方法：翻转和裁剪、变化颜色、叠加多个图像增广方法；</p>
<p>为了在预测时获得准确结果，图像增广通常仅用于训练集，而不在预测时使用含随机操作的图像增广。</p>
<p>Gluon数据集提供的transform模块中，transform_first函数将图像增广应用在每个训练样本（图像和标签）的第一个元素，即图像之上。</p>
<h3 id="用增广后图像训练模型："><a href="#用增广后图像训练模型：" class="headerlink" title="用增广后图像训练模型："></a>用增广后图像训练模型：</h3><p>1、定义try_all_gpus函数，获取所有能用的GPU；</p>
<p>2、定义辅助函数_get_batch将小批量数据样本batch划分，并复制到ctx变量所指定的各个显存上；</p>
<p>3、定义evaluate_accuracy函数来评价模型的分类准确性，该函数通过辅助函数_get_batch使用ctx变量所包含的所有GPU来评价模型；</p>
<p>4、定义train函数使用多GPU训练并评价模型；</p>
<p>5、最终定义train_with_data_aug函数，来使用图像增广来训练模型；该函数获取所有GPU，并将Adam算法作为训练优化算法，之后将图像增广应用于训练数据集上，最后调用刚定义的train函数训练并评价模型。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">train_with_data_aug</span><span class="params">(train_augs, test_augs, lr = <span class="number">0.001</span>)</span>:</span></span><br><span class="line">    batch_size, ctx, net = <span class="number">256</span>, try_all_gpus(), d2l.resnet18(<span class="number">10</span>)</span><br><span class="line">    net.initialize(ctx=ctx, init=init.Xavier())</span><br><span class="line">    trainer = gluon.Trainer(net.collect_params(), <span class="string">'adam'</span>, &#123;<span class="string">'learning_rate'</span>: lr&#125;)</span><br><span class="line">    loss = gloss.SoftmaxCrossEntropyLoss()</span><br><span class="line">    train_iter = load_cifar10(<span class="literal">True</span>, train_augs, batch_size)</span><br><span class="line">    test_iter = load_cifar10(<span class="literal">False</span>, test_augs, batch_size)</span><br><span class="line">    train(train_iter, test_iter, net, loss, trainer, ctx, num_epochs=<span class="number">10</span>)</span><br></pre></td></tr></table></figure>





<h2 id="图像微调"><a href="#图像微调" class="headerlink" title="图像微调"></a>图像微调</h2><p>由于收集数据所需要的成本较高，应用迁移学习：将从源数据集学到的知识迁移到目标数据集上。例：可从图形数据集训练的模型中抽取较通用的模型特征，边缘、纹理、形状、物体组成识别等等。</p>
<p>微调时常用的一种迁移学习技术，当目标数据集远小于源数据集时，微调有助于提升模型的泛化能力，步骤包括：</p>
<p>1、在源数据集上预训练一个神经网络模型，即源模型；</p>
<p>2、创建一个新的神经网络模型，即目标模型，其复制了源模型上除了输出层以外的所有模型设计与参数。假设该模型参数包含了源数据集上学习到的知识，且同样适用于目标数据集。</p>
<p>3、为目标模型添加一个输出大小为目标数据集类别个数的输出层，并初始化该层的模型参数。</p>
<p>4、在目标数据集上训练目标模型，将从头训练输出层，而其余层的参数将会基于源模型的参数微调得到。</p>
<h3 id="热狗识别"><a href="#热狗识别" class="headerlink" title="热狗识别"></a>热狗识别</h3><p>基于一个小数据集对在ImageNet数据集上训练好的ResNet模型进行微调。</p>
<p>1、获取数据集；</p>
<p>2、定义和初始化模型：使用在ImageNet数据集上预训练的ResNet-18作为源模型，该源模型实例含有两个成员变量，即features和output。前者包括模型输出层以外的所有层，后者为模型的输出层，这样的划分方便微调除输出层以外所有层的模型参数。</p>
<p>3、微调模型：先定义一个使用微调的训练函数train_fine_tuning，以便多次调用。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">train_fine_tuning</span><span class="params">(net, learning_rate, batch_size=<span class="number">128</span>, num_epochs=<span class="number">5</span>)</span>:</span></span><br><span class="line">    train_iter = gdata.DataLoader(train_imgs.transform_first(train_augs), batch_size, shuffle=<span class="literal">True</span>)</span><br><span class="line">    test_iter = gdata.DataLoader(test_imgs.transform_first(test_augs), batch_size)</span><br><span class="line">    ctx = d2l.try_all_gpus()</span><br><span class="line">    net.collect_params().reset_ctx(ctx)</span><br><span class="line">    net.hybridize()</span><br><span class="line">    loss = gloss.SoftmaxCrossEntropyLoss()</span><br><span class="line">    trainer = gluon.Trainer(net.collect_params(), <span class="string">'sgd'</span>, &#123;<span class="string">'learning_rate'</span>: learning_rate, <span class="string">'wd'</span>: <span class="number">0.001</span>&#125;)</span><br><span class="line">    d2l.train(train_iter, test_iter, net, loss, trainer, ctx, num_epochs)</span><br></pre></td></tr></table></figure>

<p>一般来说，微调参数会使用较小的学习率；而从头训练输出层可以使用较大学习率。</p>
<h2 id="目标检测与边界框"><a href="#目标检测与边界框" class="headerlink" title="目标检测与边界框"></a>目标检测与边界框</h2><p>在图像分类任务里，假设只有一个主体目标；而目标检测往往是图像中有多个感兴趣的目标。</p>
<p>目标检测算法通常会在输入图像中采样大量的区域，，然后判断是否包含感兴趣的目标，并调整区域边缘从而更准确地预测目标的真是边界框。</p>
<p>锚框：以每个像素为中心生成多个大小和宽高比不同的边界框。</p>
<p>交并比：（若某个锚框较好地覆盖了图像的狗，那么较好该如何量化）直观的方法是，衡量锚框与真实边界框间的相似度Jaccard系数可以衡量两个集合的相似度，Jaccard系数等于二者交集大小除以二者并集大小。</p>
<p>在训练集中，将每一个锚框视为一个训练样本，为了训练目标检测模型，需为每个锚框标注两个标签：1、锚框所含目标的类别；2、真实边界框相对锚框的便宜量offset。</p>
<p>在目标检测的训练集中，每个图像已经标注了真实边界框的位置及所含目标的类别，那么生成锚框后，如何为锚框分配与其相似的真实边界框呢？</p>
<h3 id="分配真实边界框"><a href="#分配真实边界框" class="headerlink" title="分配真实边界框"></a>分配真实边界框</h3><p>1、锚框有Na个，真实边界框有Nb个，定义矩阵为Na X Nb，其第i列第j行的元素为锚框Ai与真实边界框Bj的交并比。则通过不停找出矩阵最大元素，且每找出一个元素则丢弃该行列的元素，直至矩阵丢弃完，只剩Na - Nb个锚框。</p>
<p>2、遍历剩下的锚框，只有该交并比大于预先设定的阈值时，才为锚框分配真实边界框Bj。</p>
<p>3、如果一个锚框A被分配了真实边界框B，将A的类别设为B的类别，并根据B和A的中心坐标的相对位置以及两个框的相对大小为锚框A标注偏移量。如果一个锚框没有被分配真实边界框，需将该锚框的类别设为背景，称为负类锚框。</p>
<p>4、通过contrib.nd模块中的MultiBoxTarget函数来为锚框标注偏移量和类别。该函数将背景设定为0，并从令0开始的目标类别的整数索引自加1，并通过expand_dims函数为锚框和真实边界添加样本维，并构造形状为（批量大小，包括背景的类别个数，锚框数）的任意预测结果。</p>
<h3 id="非极大值抑制"><a href="#非极大值抑制" class="headerlink" title="非极大值抑制"></a>非极大值抑制</h3><p>当锚框数量较多时，同一目标可能输出较多相似的。用非极大值抑制来移除：对一个预测边界框B，模型会计算其各个类别的预测概率，其中最大概率对应的类别即B的预测类别，且在同一图像上将预测类别置信度从高到低排列，得到列表L。从L中选取置信度最高的预测边界框B1为基准，将与B1交并比大于某阈值的从L中移除，阈值为预定的超参数，此时L保留了置信度最高的边界框并移除了与之相似的其他预测边界框。</p>
<p>多尺度目标检测</p>
<p>如果以图像每个像素中心都生成锚框，很容易生成过多锚框而造成计算量过大，方法一：在输入图像中均匀采样一小部分像素，并以采样的像素为中心生成锚框。之后既然我们已经在不同尺度下生成了不同大小的锚框，相应的需要在不同尺度下检测不同大小的目标，基于卷积神经网络有如下的方法：</p>
<p>在某尺度下，假设我们根据Ci张形状为h X w的特征图生成h X w组不同中心的锚框，且每组锚框的个数为a。</p>
<p>假设这里的Ci张特征图为卷积神经网络根据输入图像做前向运算所得的中间输出，根据感受野的定义，特征图在相同位置的Ci个单元在输入图像的感受野相同且表征了同一感受野内的输入图像信息。因此我们将这Ci个单元变换为该位置为中心生成的a个锚框的类别和偏移量，故本质上使用感受野内的信息来预测锚框。</p>
<p>因此不同大小的感受野用于检测不同大小的目标，可通过设计网络来控制输出层感受野大小，从而分别用来检测不同大小的目标。</p>
<h3 id="单发多框检测"><a href="#单发多框检测" class="headerlink" title="单发多框检测"></a>单发多框检测</h3><p>由一个基础网络块和若干多尺度特征块串联而成。其中网络块用于从原始图像中抽取特征，因此一般会选择常用的深度卷积神经网络，例如：在分类层之前截断的VGG、或者用ResNet替代。</p>
<p><img src="/../../image/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/SSD%E5%8D%95%E5%8F%91%E5%A4%9A%E6%A1%86%E6%A3%80%E6%B5%8B.png" alt="SSD单发多框检测"></p>
<p>设计基础网络，使其输出的高宽较大，这样一来基于该特征图生成的锚框数量较多，用于检测较小目标；接下来每个多尺度特征块将上一层提供的特征图的高、宽减小，使感受野变广阔，这样越靠顶部其特征图越小，生成锚框越少，适合检测尺寸大的目标。借此，单发多框检测是一个多尺度的目标检测。</p>
<h4 id="类别预测层"><a href="#类别预测层" class="headerlink" title="类别预测层"></a>类别预测层</h4><p>如果用全连接层作为输出，容易导致模型参数过多，故像NIN一样使用卷积层的通道进行输出类别的预测，来降低模型复杂度。即使用一个保持输入高、宽的卷积层，使输入、输出的空间坐标一一对应</p>
<h4 id="边界预测层"><a href="#边界预测层" class="headerlink" title="边界预测层"></a>边界预测层</h4><p>设计与类预测层类似，需要为每个锚框预测4个偏移量。</p>
<h4 id="连接多尺度的预测"><a href="#连接多尺度的预测" class="headerlink" title="连接多尺度的预测"></a>连接多尺度的预测</h4><p>由于每个尺度的特征图形状与锚框个数都可能不同，因此不同尺度预测输出形状可能不同。需要将他们变形成统一的格式并将多尺度的预测连结，从而让后续的计算更简单。</p>
<h4 id="高、宽减半块"><a href="#高、宽减半块" class="headerlink" title="高、宽减半块"></a>高、宽减半块</h4><p>为了能多尺度地检测目标，需要定义高宽减半块，其串联了两个填充为1的3X3卷积层和步幅为2的2X2最大池化层，卷积层不改变特征图形状，而后面池化层将特征图的高、宽减半。</p>
<h4 id="基础网络块"><a href="#基础网络块" class="headerlink" title="基础网络块"></a>基础网络块</h4><p>用于在原始图像中抽取特征，此处串联3个高、宽减半块，并将通道数翻倍，则当输入图像形状为256X256时，基础网络块的输出特征图的形状为32X32。</p>
<h4 id="完整的模型"><a href="#完整的模型" class="headerlink" title="完整的模型"></a>完整的模型</h4><p>单发多框检测一共包括5个模块，每个模块即生成锚框，又来预测锚框的类别与偏移量。第一模块为基础网络块，二至四模块为高宽减半块，第五模块使用全局最大池化层将高和宽降到1。</p>
<h3 id="单发多框检测训练模型"><a href="#单发多框检测训练模型" class="headerlink" title="单发多框检测训练模型"></a>单发多框检测训练模型</h3><h4 id="1、读取数据集并初始化；"><a href="#1、读取数据集并初始化；" class="headerlink" title="1、读取数据集并初始化；"></a>1、读取数据集并初始化；</h4><h4 id="2、定义损失函数与评价函数："><a href="#2、定义损失函数与评价函数：" class="headerlink" title="2、定义损失函数与评价函数："></a>2、定义损失函数与评价函数：</h4><p>一、有关锚框类别的损失，图像分类问题一般使用的：交叉熵函数</p>
<p>二、有关正类锚框偏移量的损失：预测偏移量是一个回归问题，因此不用平方损失，而用L1范数损失，即预测值与真实值之间差的绝对值。</p>
<h4 id="3、训练模型"><a href="#3、训练模型" class="headerlink" title="3、训练模型"></a>3、训练模型</h4><p>在模型的前向计算过程中生成多尺度的锚框anchors，并为每个锚框预测类别cls_preds和偏移量bbox_preds，之后根据标签信息Y为生成的每个锚框标注类别和偏移量。最后，根据这两者值来计算损失函数。</p>
<h4 id="4、预测目标"><a href="#4、预测目标" class="headerlink" title="4、预测目标"></a>4、预测目标</h4><p>在预测阶段，我们读取图像并变换尺寸，转换为卷积层所需的四维格式，通过MultiBoxDetection函数根据锚框及其预测偏移量得到预测边界框，并通过非极大值抑制移除相似的预测边界框；最后，将置信度不低于0.3的边界框筛选为最终输出。</p>
<h2 id="区域卷积神经网络R-CNN"><a href="#区域卷积神经网络R-CNN" class="headerlink" title="区域卷积神经网络R-CNN"></a>区域卷积神经网络R-CNN</h2><p>R-CNN首先对图像选取若干提议区域，并标注它们的类别和边界框，之后用卷积神经网络对每个提议区域做前向运算来抽取特征。</p>
<p><img src="/../../image/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/R-CNN.png" alt="R-CNN"></p>
<p>1、对输入图像进行选择性搜索，来选取多个高质量的提议区域，通常在多个尺度下选取，并标注类别与真实边界框；</p>
<p>2、选取一个预训练的卷积神经网络，并将其在输出层之前截断，并将每个提议区域变形为网络所需要的尺寸，并通过前向计算输出抽取的提议区域特征；</p>
<p>3、将每个提议区域的特征连同其标注的类别作为一个文本，训练多个支持向量机对目标进行分类，其中每个支持向量机用来判断样本是否属于一个实例；</p>
<p>4、将每个提议区域的特征连同其标注的边界框作为一个样本，训练线性回归模型来预测真实边界框。</p>
<h3 id="FAST-R-CNN"><a href="#FAST-R-CNN" class="headerlink" title="FAST R-CNN"></a>FAST R-CNN</h3><p>R-CNN抽取的独立特征常有大量重复计算，利用FAST R-CNN进行简化，</p>
<h3 id="FASTER-R-CNN"><a href="#FASTER-R-CNN" class="headerlink" title="FASTER R-CNN"></a>FASTER R-CNN</h3><p>将选择性搜索替换成区域提议网络，从而减少提议区域的生成数量，以达到较精确的目标检测结果。</p>
<h3 id="Mask-R-CNN"><a href="#Mask-R-CNN" class="headerlink" title="Mask R-CNN"></a>Mask R-CNN</h3><p>当训练数据还标注了每个目标在图像上的像素级位置，那么Mask R CNN模型能有效利用这些详尽的标注信息</p>
<h2 id="语义分割和数据集"><a href="#语义分割和数据集" class="headerlink" title="语义分割和数据集"></a>语义分割和数据集</h2><p>语义分割问题：关注如何将图像分割成属于不同语义类别的区域，且均为像素级，相比于锚框更加精确。</p>
<p>图像分割问题：利用像素间相关性将图像分割成若干区域，且训练时并不需要像素有关的标签信息，预测时也无法保证希望得到的语义。</p>
<p>实例分割问题：研究如何识别图像中各个目标实例的像素级区域，不仅要区分语义，还要区分不同目标实例，比如：区分两条同样语义的狗。</p>
<p>Pascal VOC2012数据集</p>
<p>由于语义分割的输出图像和标签在像素上一一对应，所以将图像随机裁剪成固定尺寸而不是缩放。</p>
<h2 id="全卷积网络FCN"><a href="#全卷积网络FCN" class="headerlink" title="全卷积网络FCN"></a>全卷积网络FCN</h2><p>FCN实现了从图像像素到像素类别的变换；FCN通过转置卷积层，将中间层特征图的高、宽变换回输入图像的尺寸，从而令预测结果与输入图像在空间维上一一对应。</p>
<h3 id="转置卷积层"><a href="#转置卷积层" class="headerlink" title="转置卷积层"></a>转置卷积层</h3><h3 id="构造模型"><a href="#构造模型" class="headerlink" title="构造模型"></a>构造模型</h3><p>1、先使用卷积神经网络来抽取图像特征；</p>
<p>2、通过1X1卷积层将通道数变换成类别个数；</p>
<p>3、通过转置卷积层，将特征图的高、宽变换为输入图像的尺寸，使模型输出与输入图像的高、宽相同，并在空间位置一一对应，最终输出的通道中包含了该空间位置像素级别的类别预测；</p>
<h2 id="样式迁移"><a href="#样式迁移" class="headerlink" title="样式迁移"></a>样式迁移</h2><p>使用卷积神经网络自动将某图像中的样式应用在另一图像上，两张输入图像：内容图像、样式图像。</p>
<h3 id="具体实施"><a href="#具体实施" class="headerlink" title="具体实施"></a>具体实施</h3><p><img src="/../../image/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89/%E6%A0%B7%E5%BC%8F%E8%BF%81%E7%A7%BB.png" alt="样式迁移"></p>
<p>1、初始化合成图像，一般初始化成内容图像，该图像便是样式迁移过程中需要迭代的模型参数。</p>
<p>2、选择一个预训练的卷积网络来抽取图像的特征，其中模型参数在训练时无需更新，深度神经网络凭借多个层级逐级抽取图像的特征，可以选择其中某些层的输出作为内容特征；</p>
<p>3、正向传播计算样式迁移的损失函数，通过反向传播迭代模型参数，即不断更新合成图像。</p>
<h3 id="预处理和后处理图像"><a href="#预处理和后处理图像" class="headerlink" title="预处理和后处理图像"></a>预处理和后处理图像</h3><p>预处理：在RGB三个通道分别做标准化，将结果变换成输入形式；</p>
<p>后处理：将输出图像中的像素值还原回标准化之前值；</p>
<h3 id="抽取特征"><a href="#抽取特征" class="headerlink" title="抽取特征"></a>抽取特征</h3><p>使用基于ImageNet数据集训练的VGG-19模型来抽取图像特征；</p>
<h3 id="定义损失函数"><a href="#定义损失函数" class="headerlink" title="定义损失函数"></a>定义损失函数</h3><p>内容损失：利用平方误差函数衡量合成图像与样式图像在内容上差异；</p>
<p>样式损失：利用平方误差函数衡量合成图像与样式图像在样式上差异；</p>
<p>总变差损失：用于降噪，使合成图像中噪点（特别亮或特别暗的颗粒像素）减少。</p>
<p>损失函数为以上三者的加权和。</p>

      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/08/28/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%BC%98%E5%8C%96%E7%AE%97%E6%B3%95/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/08/28/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E4%BC%98%E5%8C%96%E7%AE%97%E6%B3%95/" class="post-title-link" itemprop="url">优化算法与计算性能</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-08-28 12:18:39" itemprop="dateCreated datePublished" datetime="2020-08-28T12:18:39+08:00">2020-08-28</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:23:28" itemprop="dateModified" datetime="2021-11-03T16:23:28+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/" itemprop="url" rel="index"><span itemprop="name">机器学习</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <h2 id="优化与深度学习"><a href="#优化与深度学习" class="headerlink" title="优化与深度学习"></a>优化与深度学习</h2><p>一般会预定义一个损失函数，再使用优化算法试图将其最小化，这样的损失函数通常被称为优化问题的目标函数，通常只考虑最小化目标函数。由于优化算法的目标函数通常是一个基于训练集的损失函数，故优化目的在于降低训练误差，而深度学习目的在于降低泛化误差，因此需要注意过拟合问题。</p>
<p>很多优化问题并不存在解析解，因此需要通过优化算法有限次迭代模型参数来尽可能降低损失函数值。</p>
<h3 id="局部最小值"><a href="#局部最小值" class="headerlink" title="局部最小值"></a>局部最小值</h3><p>当一个优化问题的数值解在局部最优解附近时，由于目标函数有关解的梯度接近或变成0，因此最终迭代可能只令目标函数局部最小化而非全局最小化。</p>
<h3 id="鞍点"><a href="#鞍点" class="headerlink" title="鞍点"></a>鞍点</h3><p>在二维空间函数中，f(x,y) = x^2 - y^2，鞍点位置是x = 0处。且在图的鞍点位置，目标函数在x轴方向上是局部最小值，但在y轴方向上是局部最大值。</p>
<p>假设函数的输入为k维向量，输出为标量，则其海森矩阵有k个特征值；可通过该函数在对应点，其海森矩阵的特征值的正负，来判断该点为：（特征值全为负）局部最大值、（特征值全为正）局部最小值，还是（特征值有正有负）鞍点。</p>
<p>而通过随机矩阵理论可知：对一个大的高斯随机矩阵来说，任一特征值为正或负的概率均为0.5，故局部最小、最大值的可能性均为(0.5)^k，目标函数的鞍点比局部最值更常见。</p>
<h3 id="梯度下降与随机梯度下降"><a href="#梯度下降与随机梯度下降" class="headerlink" title="梯度下降与随机梯度下降"></a>梯度下降与随机梯度下降</h3><p>一维梯度下降：通过用X - nf*(x)来代替x的方法，利用该式子不断迭代x，直到达到停止条件（一般为f’(x) ^2已经足够小，或者迭代次数已到达某个值）。其中正数n通常叫做学习率，为超参数，需人工设定。学习率过小：x更新缓慢，需要更多次迭代；学习率过大：可能会导致taylor展开的不等式不一定成立，迭代x不一定减小f(x)的值。</p>
<p>多维梯度下降：方向导数给出了x沿所有可能方向的变化率，为了最小化f，希望能找到f能被下降最快的方向，故利用梯度下降算法不断降低f的值。</p>
<p>随机梯度下降：n为训练数据样本数，x为模型的参数向量。则如果使用梯度下降时，会使用各个样本的平均作为，每次自变量迭代的计算开销为O(n)，随n线性增长，因此若样本数大时，每次迭代的计算开销高。而随机梯度下降减少了计算开销，在每次迭代中随机均匀采样样本索引来计算梯度，从而减少每次迭代的开销。</p>
<h3 id="小批量随机梯度下降"><a href="#小批量随机梯度下降" class="headerlink" title="小批量随机梯度下降"></a>小批量随机梯度下降</h3><p>在每次迭代，梯度下降用整个训练集来计算梯度，而小批量梯度随机下降，利用随机均匀采样一个由样本索引组成的小批量B。</p>
<p>且由于随机采样得到梯度的方差在迭代过程中无法减小，因此实际中，小批量随机梯度下降的学习率需要在迭代过程中自我衰减。</p>
<p>在Gluon中可用创建Trainer实例来调用调优算法。</p>
<h3 id="动量法"><a href="#动量法" class="headerlink" title="动量法"></a>动量法</h3><p>梯度下降又称最陡下降：自变量在当前位置下降最快的方向，在每次迭代中梯度下降根据自变量当前位置沿着梯度来更新自变量，然而，若自变量的迭代方向仅仅取决于自变量当前位置，可能会带来问题。</p>
<p>在二维或者多维的变量中，梯度下降往往难以同时兼顾学习率与确保f(x)下降；需要确保学习率较小，从而避免自变量在竖直方向越过函数最优解，但会因此导致向最优解移动缓慢。</p>
<p>动量法：设时间步t的自变量为Xt，学习率为Nt，动量法对每次迭代的步骤做出以下修改：Vt &lt;- yV(t-1)；Xt &lt;- X(t-1) - Vt。y为动量超参数，范围在[0，1）</p>
<p>指数加权移动平均：</p>
<p>由指数加权平均理解动量法：</p>
<p>相对于小批量随机梯度下降，动量法需要对每一个自变量维护一个同它一样形状的速度变量，且在超参数中多了动量超参数。</p>
<p>在Gluon中，需要在Trainer实例中通过momentum来指定动量超参数，即可使用动量法。</p>
<h3 id="AdaGrad算法"><a href="#AdaGrad算法" class="headerlink" title="AdaGrad算法"></a>AdaGrad算法</h3><p>动量法依赖指数加权移动平均，使得自变量的更新方向更加一致，从而降低自变量在梯度较大的维度发散的可能。</p>
<p>而AdaGrad算法根据自变量在每个维度的梯度大小，来调整各个维度的学习率，从而避免统一的学习率难以适应所有维度的问题。</p>
<p>AdaGrad算法会使用一个小批量随机梯度Gt按元素平方的累加变量St：</p>
<p>Gluon中使用名称为”adagrad”的Trainer实例来调用该算法训练模型。</p>
<h3 id="RMSProp算法"><a href="#RMSProp算法" class="headerlink" title="RMSProp算法"></a>RMSProp算法</h3><p>AdaGrad算法在迭代后期由于学习率过小，可能比较难找一个有用的解：因此用RMSProp算法改良后。</p>
<p>不同于AdaGrad算法里状态变量St是截至时间步t所有小批量随机梯度Gt按元素平方和。RMSProp算法将这些梯度按元素平方做指数加权移动平均，即</p>
<p>Gluon中使用名称为”rmsprop”的Trainer实例来调用该算法训练模型，且超参数由gammal指定。</p>
<p>还有AdaDelta算法、Adam算法</p>
<h2 id="深度学习计算性能"><a href="#深度学习计算性能" class="headerlink" title="深度学习计算性能"></a>深度学习计算性能</h2><h3 id="命令式和符号式混合编程"><a href="#命令式和符号式混合编程" class="headerlink" title="命令式和符号式混合编程"></a>命令式和符号式混合编程</h3><p>之前一般使用Sequential类来串联多个层，先为了使用混合式编程，使用HybridSequential类来替换Sequential类。</p>
<h3 id="异步运算"><a href="#异步运算" class="headerlink" title="异步运算"></a>异步运算</h3><p>MXNet使用异步运算来提升性能，通过前端线程与后端线程的交互进行异步运算：前端线程无需等待当前指令从后端线程返回结果就继续执行后面的指令。</p>
<p>但同样异步运算会占据额外的内存：由于深度学习模型往往比较大，且内存资源通常有限，因此在训练模型时通常使用同步函数，而不用异步运算。</p>
<h3 id="自动并行计算"><a href="#自动并行计算" class="headerlink" title="自动并行计算"></a>自动并行计算</h3><p>MXNet后端会自动构建计算图，依据该图，系统会自动知道所有计算的依赖关系。</p>
<p>包括CPU与GPU的并行计算、多GPU计算、数据并行。</p>

      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/08/25/C++/C%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/08/25/C++/C%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/" class="post-title-link" itemprop="url">C语言程序设计</a>
        </h2>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2020-08-25 20:54:02" itemprop="dateCreated datePublished" datetime="2020-08-25T20:54:02+08:00">2020-08-25</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-03 16:35:54" itemprop="dateModified" datetime="2021-11-03T16:35:54+08:00">2021-11-03</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/C-%E5%88%9D%E5%AD%A6/" itemprop="url" rel="index"><span itemprop="name">C++初学</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
          <h2 id="一、基础知识"><a href="#一、基础知识" class="headerlink" title="一、基础知识"></a>一、基础知识</h2><h3 id="在命令行中进行编译运行"><a href="#在命令行中进行编译运行" class="headerlink" title="在命令行中进行编译运行"></a>在命令行中进行编译运行</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">~/project ls -l #执行命令ls，用于列出当前所在计算机存储位置中的文件和目录，并为其配置参数-l</span><br><span class="line">-rw-r--r-- 1 user user 112 Aug 25 20:48 main.c </span><br><span class="line">~/project gcc -o program main.c </span><br><span class="line"><span class="meta">#</span><span class="bash">gcc为编译器名称，用该命令告诉gcc，将main.c的代码文件编译成名为program的可执行文件</span></span><br><span class="line">~/project ls -l</span><br><span class="line">-rw-r--r-- 1 user user  112 Aug 25 20:48 main.c                                                   </span><br><span class="line">-rwxrwxr-x 1 user user 8512 Aug 25 21:35 program  #目录中新增了program的可执行文件</span><br><span class="line">./program #执行程序</span><br></pre></td></tr></table></figure>



<h3 id="变量相关"><a href="#变量相关" class="headerlink" title="变量相关"></a>变量相关</h3><p>变量名：由大、小写字母，下划线，数字组成；数字不能开头；不能是有特定含义的保留字。</p>
<h3 id="作用域："><a href="#作用域：" class="headerlink" title="作用域："></a>作用域：</h3><p>变量声明语句之后，包裹了它声明语句的最内一层{}中，且一个变量在其作用域内仅能声明一次，但能够赋值多次，只要是在其作用域内的赋值，均起作用。</p>
<p> 这些在结构化语句的内部的变量的作用域为结构化语句内部。注意，对于switch中在case内部定义的变量的作用域就是在当前case。我们可以简单理解为在大括号内部定义的变量，其作用域就是在当前大括号中，在当前大括号外部无效。对于循环嵌套和分支嵌套程序来说都是一样的。关于这一点不再赘述。</p>
<p>注意，当一个嵌套结构中出现两个不同作用域的变量时，变量的名称可以相同，在使用时以其小作用域为准。</p>
<p>与局部变量相对的就是全局变量，我们把定义在函数外部的变量称为全局变量，这些变量的作用域为整个程序，也就是所有的函数和结构化语句都能使用它们。</p>
<p>甚至多个源文件一起编译时，全局变量在其他文件中也能够生效需要用extern关键字在函数外部声明一个文件外部变量。</p>
<h3 id=""><a href="#" class="headerlink" title=""></a></h3><h3 id="递归问题"><a href="#递归问题" class="headerlink" title="递归问题"></a>递归问题</h3><p>在头递归的实现中，我们在进行下一层的调用前，没有进行计算，只有在下一层的返回之后，我们才完成了这一层的运算。</p>
<p>在尾递归的实现中，我们在进行下一层的调用前，会先进行计算，而在最终一般条件满足时，会将计算的结果逐层直接返回。</p>
<h3 id="声明与实现分离"><a href="#声明与实现分离" class="headerlink" title="声明与实现分离"></a>声明与实现分离</h3><p>如果采用直接定义的方式来创造函数，则需要时刻关注它们之间依赖关系，并正确排序，不现实。需要进行声明与实现的分离，从而简化这一过程。</p>
<p>只需要在需要用到该函数前进行声明即可，定义可放在执行程序的后面位置，函数声明时可以不写函数参数名，只写参数类型。</p>
<h3 id="变量地址做函数参数"><a href="#变量地址做函数参数" class="headerlink" title="变量地址做函数参数"></a>变量地址做函数参数</h3><p>swap函数中，由于该函数定义的形式参数a,b作用域有限，因此swap函数内的交换并不会影响main函数中x，y大的值。此时，需修改成传入参数x、y的地址，直接对其地址进行操作。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">swap</span><span class="params">(<span class="keyword">int</span> *a, <span class="keyword">int</span> *b)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> x,y;</span><br><span class="line">    swap(&amp;x, &amp;y);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">swap</span><span class="params">(<span class="keyword">int</span> *a, <span class="keyword">int</span> *b)</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> temp;</span><br><span class="line">    temp = *a;</span><br><span class="line">    *a = *b;</span><br><span class="line">    *b = temp;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="函数地址做函数参数"><a href="#函数地址做函数参数" class="headerlink" title="函数地址做函数参数"></a>函数地址做函数参数</h3><p>C语言中函数与变量类似，也有其自己的内存地址，但函数不能像变量一样可以进行值传递，在想要将函数作为另一个函数的参数进行传递时，需要传递它的地址。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">g</span><span class="params">(<span class="keyword">float</span> (*f)(<span class="keyword">int</span>), <span class="keyword">int</span> a)</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> f(a);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上面这种情况，函数g需要有一个形式参数来接收函数地址，其第一个参数需要一个返回值类型为float且有一个int类型参数的函数；第二个参数就是普通的int类型值</p>
<p>其实直接写f(a)和float (*f)(int)来调用其地址本质上是一样的。因此声明时需要如上所示去取函数的地址，而调用时，直接函数名与变量一起传入也是可以的。g(f(x), a)。</p>
<h3 id="有关代码风格的空格"><a href="#有关代码风格的空格" class="headerlink" title="有关代码风格的空格"></a>有关代码风格的空格</h3><p>哪些使用空格的地方：</p>
<p>1、+、-、&gt;、==、|、&amp;&amp;等双目运算符前后；</p>
<p>2、if、switch、for、while等关键字，函数名和之后的左小括号之间；</p>
<p>3、不在行尾的逗号、分号之后，例如for循环中的分号之后；</p>
<p>4、必须加空格的情况：如return后面不加空格就会报语法错误的情况。</p>
<h3 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h3><p>相当于定义了一系列地址相邻的元素，与取变量地址的方式一致，可以通过&amp;radius[1]的方式取得数组radius在索引位置1元素的地址。在C语言中，对一个元素的地址加上位移值n得到的就是这个元素往后数n后所在元素的地址。</p>
<p>且一般来说，在地址上进行运算的方式访问数组的效率比利用索引更快，例如：你只希望访问数组中每一个元素一次时，可用while循环内使用地址上运算的方式，使用数组中每一个元素的值，而无需关心数组的索引是谁。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> *p_radius;</span><br><span class="line">p_radius = &amp;radius[<span class="number">0</span>];</span><br><span class="line"><span class="comment">//这里*(p_radius + 1)或者（&amp;radius[0] + 1）都会得到radius[1]元素的地址。</span></span><br></pre></td></tr></table></figure>

<h3 id="字符串的本质是数组"><a href="#字符串的本质是数组" class="headerlink" title="字符串的本质是数组"></a>字符串的本质是数组</h3><p>字符串实际上是一个元素为字符的数组，例如“Hello”由五个字母字符与一个空字符\0组成；任何字符串的内部表示都会以空字符‘\0’作为结尾，故可以以此方式找到字符串结尾。</p>
<p>同样，在C中提供字符数组初始化的简化方式：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">char</span> <span class="built_in">string</span>[] = <span class="string">"Hello"</span>;</span><br></pre></td></tr></table></figure>

<p>字符串更严谨应该被称为 字符串字面量，其表现为一对双引号包裹的0个或者多个字符；字面量并非仅包含字符串常量</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> a;</span><br><span class="line">a = <span class="number">1234</span>;</span><br><span class="line"><span class="comment">//语句中的1234其实就是一个整数型字面量，其实是将一个整数型字面量的值放入了变量中作为值。在字面量后往往需要增加一个后缀标记类型。L：长类型；U：无符号类型；F：浮点类型。</span></span><br><span class="line"><span class="comment">//除了十进制，也可用其他进制表示字面量。</span></span><br></pre></td></tr></table></figure>

<p>除了用字符数组存储字符串，也可声明一个用于存储字符地址的变量操作字符串</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="comment">//string的地址是内存栈区的地址；string2则是直接关联到"Hello"字符串字面量在内存中字面量池的地址。</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span> <span class="built_in">string</span>[] = <span class="string">"Hello"</span>;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%s\n"</span>, <span class="built_in">string</span>);</span><br><span class="line">    <span class="keyword">char</span> *string2 = <span class="string">"Hello"</span>;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%s\n"</span>, string2);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%p\n"</span>, &amp;<span class="built_in">string</span>); <span class="comment">//0x7fff09dd0480</span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%p\n"</span>, string2);<span class="comment">//0x4allc4</span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%p\n"</span>, &amp;<span class="string">"Hello"</span>);<span class="comment">//0x4allc4</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="按位运算"><a href="#按位运算" class="headerlink" title="按位运算"></a>按位运算</h3><h3 id="结构体"><a href="#结构体" class="headerlink" title="结构体"></a>结构体</h3><p>使用struct定义完结构体后，每当我们需要使用结构体时都需要写一次struct关键字，而其实C语言中提供了一种为某一已知类型添加别名的方式：typedef；typedef 原类型 类型别名</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">point</span> <span class="title">Point</span>;</span></span><br><span class="line"><span class="comment">//完成设置别名后再进行变量声明时，可以不写struct point point1;</span></span><br><span class="line">Point point1;</span><br><span class="line"><span class="comment">//也可以在定义结构体时同时在前面加上typedef，这样可以把两步合二为一</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">point</span>&#123;</span></span><br><span class="line">    <span class="keyword">float</span> x;</span><br><span class="line">    <span class="keyword">float</span> y;</span><br><span class="line">&#125; Point;</span><br></pre></td></tr></table></figure>

<p>函数的返回值也可以通过结构体的方式来进行返回，同样传入参数也可以以结构体的形式传入， 但若以结构体变量值的形式进行传递参数，这种传值的效率相对来说是低的（特别是结构体内成员特别多时），当vector_add函数不会改变传入参数的值时，没有必要采用会使用额外内存并需要赋值传入值到额外内存的“传值”作参数的方式，可将传入的参数改成指针的形式。</p>
<p>同时这样修改后调用函数参数时，也要加上取地址符号&amp;。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;math.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">point</span> &#123;</span></span><br><span class="line">    <span class="keyword">float</span> x;</span><br><span class="line">    <span class="keyword">float</span> y;</span><br><span class="line">&#125; Vector;</span><br><span class="line"></span><br><span class="line"><span class="function">Vector <span class="title">vector_add</span><span class="params">(Vector *v1, Vector *v2)</span> </span>&#123;</span><br><span class="line">    Vector v_result;</span><br><span class="line">    v_result.x = v1-&gt;x + v2-&gt;x;</span><br><span class="line">    v_result.y = v1-&gt;y + v2-&gt;y;</span><br><span class="line">    <span class="keyword">return</span> v_result;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    Vector v1 = &#123; <span class="number">2.4f</span>, <span class="number">2.5f</span> &#125;;</span><br><span class="line">    Vector v2 = &#123; <span class="number">3.7f</span>, <span class="number">4.4f</span> &#125;;</span><br><span class="line">    Vector v_result;</span><br><span class="line">    v_result = vector_add(&amp;v1, &amp;v2);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"(%f, %f)\n"</span>, v_result.x, v_result.y);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>以后再用到(*结构体指针名).结构体成员元素名形式的代码时，都可以将其写为：结构体指针名-&gt;结构体成员元素名。</p>
<p>用结构体构建一个简单链表的方法如下图：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">node</span>&#123;</span></span><br><span class="line">    <span class="keyword">int</span> number;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">node</span>*<span class="title">next</span>;</span></span><br><span class="line">&#125;Node;</span><br><span class="line"></span><br><span class="line"><span class="function">Node *<span class="title">create_node</span><span class="params">(<span class="keyword">int</span> new_number)</span></span>&#123;</span><br><span class="line">    Node *temp_node;</span><br><span class="line">    temp_node = (Node *) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line">    temp_node-&gt;number = new_number;</span><br><span class="line">    temp_node-&gt;next = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="keyword">return</span> temp_node;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    Node *head;</span><br><span class="line">    head = create_node(<span class="number">1</span>);</span><br><span class="line">    head-&gt;next = create_node(<span class="number">2</span>);</span><br><span class="line">    head-&gt;next-&gt;next = create_node(<span class="number">3</span>);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, head-&gt;next-&gt;number);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="约瑟夫环问题"><a href="#约瑟夫环问题" class="headerlink" title="约瑟夫环问题"></a>约瑟夫环问题</h3><p>N个同学围成圆圈，每个人被顺序地编了一个序号，从编号为K的人开始报1，之后按顺序增长，直至报数字M的人出列，出列人的下一个人从1继续开始报数，重复该过程直至所有人均出列。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> <span class="title">node</span> &#123;</span></span><br><span class="line">    <span class="keyword">int</span> data;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">node</span> *<span class="title">next</span>;</span></span><br><span class="line">&#125; Node;</span><br><span class="line"></span><br><span class="line"><span class="function">Node *<span class="title">circle_create</span><span class="params">(<span class="keyword">int</span> n)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">count_off</span><span class="params">(Node *head, <span class="keyword">int</span> n, <span class="keyword">int</span> k, <span class="keyword">int</span> m)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> n, k, m;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">"%d%d%d"</span>, &amp;n, &amp;k, &amp;m);</span><br><span class="line">    Node *head = circle_create(n);</span><br><span class="line">    count_off(head, n, k, m);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">Node *<span class="title">circle_create</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">    Node *temp, *new_node, *head;</span><br><span class="line">    <span class="keyword">int</span> i;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 创建第一个链表节点并加数据</span></span><br><span class="line">    temp = (Node *) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line">    head = temp;</span><br><span class="line">    head-&gt;data = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 创建第 2 到第 n 个链表节点并加数据</span></span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">2</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        new_node = (Node *) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</span><br><span class="line">        new_node-&gt;data = i;</span><br><span class="line">        temp-&gt;next = new_node;</span><br><span class="line">        temp = new_node;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 最后一个节点指向头部构成循环链表</span></span><br><span class="line">    temp-&gt;next = head;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> head;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">count_off</span><span class="params">(Node *head, <span class="keyword">int</span> n, <span class="keyword">int</span> k, <span class="keyword">int</span> m)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> i, j;</span><br><span class="line">    Node *newNode, *beginNode;</span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; n - <span class="number">1</span>; i++)&#123;</span><br><span class="line">        beginNode = head-&gt;next;</span><br><span class="line">    &#125;</span><br><span class="line">    newNode = head-&gt;next;</span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; k - <span class="number">1</span>; i++)&#123;</span><br><span class="line">        beginNode = head;</span><br><span class="line">        head = newNode;</span><br><span class="line">        newNode = head-&gt;next;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; n; i++)&#123;</span><br><span class="line">        <span class="keyword">for</span> (j = <span class="number">1</span>; j &lt; m ; j++)&#123;</span><br><span class="line">            beginNode = head;</span><br><span class="line">            head = newNode;</span><br><span class="line">            newNode = head-&gt;next;</span><br><span class="line">        &#125;</span><br><span class="line"><span class="keyword">if</span> (m == <span class="number">2</span> &amp;&amp; i == n - <span class="number">1</span>) head = newNode;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"%d"</span>, head-&gt;data);</span><br><span class="line">        <span class="keyword">if</span> (i != n - <span class="number">1</span>)</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">" "</span>); </span><br><span class="line">        head = newNode;</span><br><span class="line">        newNode = head-&gt;next;</span><br><span class="line">        beginNode-&gt;next = head;</span><br><span class="line">      &#125;</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="共用体"><a href="#共用体" class="headerlink" title="共用体"></a>共用体</h3><p>结构体的特性解决了一系列不同类型变量可以怎么放在一起组织的问题，而共用体则使多种不会同时出现的变量共用一块内存成为了可能，关键字union，共用体所占用的内存空间是被公用的，可通过两种或多种不同类型描述成员进行访问，且无论通过哪种方式进行访问，访问的是同一块内存空间。共用体类型变量的成员在内存中地址相同。</p>
<h3 id="枚举enumeration"><a href="#枚举enumeration" class="headerlink" title="枚举enumeration"></a>枚举enumeration</h3><p>枚举由一系列的整数成员，表示这一数据类型的变量可以取的所有可能值，但是这些值都不直接以字面量形式存在，每个值都被单独给予一个名字，同样也可以给多个枚举成员进行显性的编号。</p>
<p>声明一个该枚举类型的变量时，只能取定义过的枚举类型中的成员名作为值，枚举类型的成员不能有结构体和共用体变量。</p>
<h2 id="二、简单算法"><a href="#二、简单算法" class="headerlink" title="二、简单算法"></a>二、简单算法</h2><h3 id="牛顿迭代法"><a href="#牛顿迭代法" class="headerlink" title="牛顿迭代法"></a>牛顿迭代法</h3><p>多数方程不存在求根方式，因此用牛顿法寻找方程的近似跟，时间复杂度为log n。</p>
<p><img src="/../../image/C%E8%AF%AD%E8%A8%80%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/%E7%89%9B%E9%A1%BF%E8%BF%AD%E4%BB%A3%E6%B3%95.png" alt="牛顿迭代法"></p>
<p>步骤：1、确定迭代变量；2、建立迭代关系式；3、对迭代过程进行控制。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;math.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> EPSILON 1e-6</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">f</span><span class="params">(<span class="keyword">double</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">2</span> * <span class="built_in">pow</span>(x, <span class="number">3</span>) - <span class="number">4</span> * <span class="built_in">pow</span>(x, <span class="number">2</span>) + <span class="number">3</span> * x - <span class="number">6</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">f_prime</span><span class="params">(<span class="keyword">double</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">6</span> * <span class="built_in">pow</span>(x, <span class="number">2</span>) - <span class="number">8</span> * x + <span class="number">3</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">h</span><span class="params">(<span class="keyword">double</span> x)</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">pow</span>(x,<span class="number">3</span>) - <span class="number">4</span> * <span class="built_in">pow</span>(x,<span class="number">2</span>) + <span class="number">3</span> * x - <span class="number">6</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">h_prime</span><span class="params">(<span class="keyword">double</span> x)</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">3</span> * <span class="built_in">pow</span>(x,<span class="number">2</span>) - <span class="number">8</span> * x + <span class="number">3</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">newton</span><span class="params">(<span class="keyword">double</span> (*fp)(<span class="keyword">double</span>), <span class="keyword">double</span>(*fp_prime)(<span class="keyword">double</span>))</span> </span>&#123;</span><br><span class="line">    <span class="keyword">double</span> x = <span class="number">1.5</span>;</span><br><span class="line">    <span class="keyword">while</span> (<span class="built_in">fabs</span>(fp(x)) &gt; EPSILON)&#123;</span><br><span class="line">        x = x - fp(x) / fp_prime(x);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> x;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%g\n"</span>, newton(f, f_prime));</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%g\n"</span>, newton(h, h_prime));</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="二分法"><a href="#二分法" class="headerlink" title="二分法"></a>二分法</h3><p>二分法同样是一个求方程近似跟的方法，在使用二分法近似求解时，先设定一个迭代区间，且区间两边自变量x对应的F(X)是异号的，之后计算两端中点位置x对应的f(x)，再更新迭代区间，并确保迭代区间两端x对应的函数值还是异号，重复过程直至中点x对应的f(x)小于某个值。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;math.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> EPSILON 1e-7</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">bisection</span><span class="params">(<span class="keyword">int</span> p, <span class="keyword">int</span> q, <span class="keyword">double</span> (*func)(<span class="keyword">int</span>, <span class="keyword">int</span>, <span class="keyword">double</span>))</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> p, <span class="keyword">int</span> q, <span class="keyword">double</span> x)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> p;</span><br><span class="line">    <span class="keyword">int</span> q;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &amp;p, &amp;q);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%.4f\n"</span>, bisection(p, q, f));</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">bisection</span><span class="params">(<span class="keyword">int</span> p, <span class="keyword">int</span> q, <span class="keyword">double</span> (*func)(<span class="keyword">int</span>, <span class="keyword">int</span>, <span class="keyword">double</span>))</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> forward, backward;</span><br><span class="line">    <span class="keyword">if</span>(func(p, q, <span class="number">20</span>) &gt; <span class="number">0</span>)&#123;</span><br><span class="line">        forward = <span class="number">20</span>;</span><br><span class="line">        backward = <span class="number">-20</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span>&#123;</span><br><span class="line">        forward = <span class="number">-20</span>;</span><br><span class="line">        backward = <span class="number">20</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">int</span> x = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span>(<span class="built_in">fabs</span>(f(p, q, x)) &gt; EPSILON)&#123;</span><br><span class="line">        <span class="keyword">if</span>(f(p, q, x) &gt; <span class="number">0</span>)&#123;</span><br><span class="line">            forward = x;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> backward = x;</span><br><span class="line">        x = (backward + forward)/<span class="number">2</span>;</span><br><span class="line">    &#125;       </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> p, <span class="keyword">int</span> q, <span class="keyword">double</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> p * x + q;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="质数筛法"><a href="#质数筛法" class="headerlink" title="质数筛法"></a>质数筛法</h3><p>与之前的对每一个数依次判断是否为质数的方式不同，筛法的思想是“标注出所有非质数，输出所有没被标记的数字”，声明了一个mark数组，用于标记所有质数。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;math.h&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"2\n"</span>);</span><br><span class="line">    <span class="keyword">int</span> digit;</span><br><span class="line">    <span class="keyword">int</span> divisor;</span><br><span class="line">    <span class="keyword">for</span> (digit = <span class="number">3</span>; digit &lt;= <span class="number">15</span>; digit += <span class="number">2</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (divisor = <span class="number">3</span>; divisor &lt; <span class="built_in">sqrt</span>(digit); divisor += <span class="number">2</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (digit % divisor == <span class="number">0</span>)&#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (divisor == digit)&#123;</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, digit);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>质数筛法的逻辑：对于n以内的筛选来说，如果n为合数，c为n的最小因数，1&lt; C*C &lt; n；故只要找到了c就可以确定n是合数，并将n进行标记，通过这样的一个个筛选，将容易得到的合数均筛选出去。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> n = <span class="number">15</span>;</span><br><span class="line">    <span class="keyword">int</span> mark[<span class="number">16</span>] = &#123;</span><br><span class="line">        <span class="number">1</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>,</span><br><span class="line">        <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>,</span><br><span class="line">        <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>,</span><br><span class="line">        <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span></span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">int</span> c;</span><br><span class="line">    <span class="keyword">int</span> j;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (c = <span class="number">2</span>; c * c &lt;= n; c++) &#123;</span><br><span class="line">        <span class="keyword">if</span>(mark[c] != <span class="number">1</span>)&#123;</span><br><span class="line">            <span class="keyword">for</span>(j = <span class="number">2</span>; j &lt;= n / c;j++)&#123;</span><br><span class="line">                mark[c * j] = <span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (c = <span class="number">2</span>; c &lt;= n; c++)&#123;</span><br><span class="line">        <span class="keyword">if</span>(mark[c] != <span class="number">1</span>)&#123;</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, c);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="折半查找"><a href="#折半查找" class="headerlink" title="折半查找"></a>折半查找</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">BinSearch</span><span class="params">(<span class="keyword">int</span> arr[], <span class="keyword">int</span> len, <span class="keyword">int</span> key)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> low = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> high = len - <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> mid;</span><br><span class="line">    <span class="keyword">while</span>(low &lt;= high)&#123;</span><br><span class="line">        mid = (low + high) / <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span>(key == arr[mid])</span><br><span class="line">            <span class="keyword">return</span> mid + <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span>(key &gt; arr[mid])</span><br><span class="line">            low = mid + <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            high = mid - <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> n;</span><br><span class="line">    <span class="keyword">int</span> k;</span><br><span class="line">    <span class="keyword">int</span> numbers[<span class="number">1000001</span>];</span><br><span class="line">    <span class="keyword">int</span> m;</span><br><span class="line">    <span class="keyword">int</span> i;</span><br><span class="line">    <span class="keyword">int</span> j;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 反复读入数字和查找数字的数量</span></span><br><span class="line">    <span class="keyword">while</span> (<span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &amp;n, &amp;k) != EOF) &#123;</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 读入给定的数字</span></span><br><span class="line">        <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &amp;numbers[i]);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; k; j++) &#123;</span><br><span class="line">            <span class="comment">// 读入待查找的数字，</span></span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &amp;m);</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%d"</span>,BinSearch(numbers, n, m));</span><br><span class="line">            <span class="comment">// 请在下面完成查找读入数字的功能 </span></span><br><span class="line">            <span class="keyword">if</span>(j &lt; k<span class="number">-1</span>)</span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">" "</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="递归问题-1"><a href="#递归问题-1" class="headerlink" title="递归问题"></a>递归问题</h3><p>有时候递归会使时间复杂度过高，是因为使用了多次的重复计算，可以用数组来存储之前计算的值，从而避免简单的运算重复进行。经典的爬楼梯问题代码如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> n, a, i;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &amp;n);</span><br><span class="line">    <span class="keyword">int</span> arr[n];</span><br><span class="line">    arr[<span class="number">0</span>] = <span class="number">0</span>;arr[<span class="number">1</span>] = <span class="number">0</span>;arr[<span class="number">2</span>] = <span class="number">1</span>;arr[<span class="number">3</span>] = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">4</span>; i &lt;= n; i++)&#123;</span><br><span class="line">        arr[i] = arr[i<span class="number">-2</span>] + arr[i<span class="number">-3</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%d"</span>, arr[n]);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="冒泡排序"><a href="#冒泡排序" class="headerlink" title="冒泡排序"></a>冒泡排序</h3><p>基本思想：将数组中每个相邻元素进行两两比较，按照较小元素在前的原则决定是否进行交换，这样每一轮执行之后，最小元素就被换至了最后一位。完成第一轮后，我们从头进行第二轮的比较，直至倒数第二位（因为最后一位是已经被排序好的），依次进行直至所有元素被排列成预期的顺序为止。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//当有5个数待排序时，可写出如下的程序。</span></span><br><span class="line"><span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; <span class="number">5</span>; j++)&#123;</span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; <span class="number">4</span> - j; i++)&#123;</span><br><span class="line">        swap(a[i], a[i+<span class="number">1</span>]);</span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> n = <span class="number">10</span>;</span><br><span class="line">    <span class="keyword">int</span> m;</span><br><span class="line">    <span class="keyword">int</span> numbers[<span class="number">10</span>];</span><br><span class="line">    <span class="keyword">int</span> i, j;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 读入给定的数字</span></span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">        <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &amp;numbers[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; n; i++)</span><br><span class="line">        <span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; n - <span class="number">1</span> - i; j++)&#123;</span><br><span class="line">            <span class="keyword">if</span>(numbers[j] &lt; numbers[j+<span class="number">1</span>])&#123;</span><br><span class="line">                m = numbers[j];</span><br><span class="line">                numbers[j] = numbers[j+<span class="number">1</span>];</span><br><span class="line">                numbers[j+<span class="number">1</span>] = m;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; n; i++)&#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"%d"</span>, numbers[i]);</span><br><span class="line">        <span class="keyword">if</span>(i != n<span class="number">-1</span>)&#123;</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">" "</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="选择排序"><a href="#选择排序" class="headerlink" title="选择排序"></a>选择排序</h3><p>核心思想：根据从小到大的排序需求，它每一次从到排序的数据元素中选择出最小的元素，移动至序列的起始位置，然后在剩余的待排序元素中进行排序。</p>
<p>用两层循环来实现：1、寻找最小的元素需要一层循环；2、逐个被选出也需要一层循环。</p>
<h3 id="螺旋输出矩阵"><a href="#螺旋输出矩阵" class="headerlink" title="螺旋输出矩阵"></a>螺旋输出矩阵</h3><p>对任意的给定m行、n列的矩阵，按顺时针螺旋的顺序输出矩阵中所有的元素.</p>
<p>找规律，由外向内一层层进行for循环打印，最外层循环控制有多少层，每层分为（上方、右侧、下方、左侧）四个递增的循环，直至最后一层打印完；如果输出N为奇数，将会有N/2 + 1层</p>
<h4 id="优化后的螺旋矩阵"><a href="#优化后的螺旋矩阵" class="headerlink" title="优化后的螺旋矩阵"></a>优化后的螺旋矩阵</h4><p>当然它的规律很简单，直接的方法就是先申请一个矩阵，然后按螺旋方向填入相应的元素，填充完毕后再打印出来。它的时间按复杂为O(n2)，已经是最优的（为什么？）。空间复杂度也为O(n2）。似乎已经很好了。 但是还不够好。</p>
<p>按照矩阵规律填充元素时，我们是随机访问矩阵元素的（如果可以按顺序访问，根本不用先存起来再打印）。随机访问内存，效率当然不高。所以即使时间复杂度已为最优，但那只是理论上的最优，在实践中表现并不一定就好。</p>
<p>假如能根据行列号直接计算出对应的矩阵元素就好了。当n给定后，这个矩阵就已经唯一确定了，那么每一个元素也是确定的。也就是说，每一个位置放什么元素仅仅取决于n。因此我们可以找到一个函数<em>element</em>(<em>i, j</em>)，将行号i和列号j映射成对应这个行列号的元素。当然这个函数肯定不是一个简单的函数，不是一眼就可以看出来的，但也并不是不可能。</p>
<p>现在我们就来考查一下这个矩阵有什么特点。注意观察一下螺旋矩阵的最外层，它的左上角的元素是最小的，然后沿顺时针方向递增，就如同一个环一样（比如n为4时，1, 2, …, 12就是最外面一层环）。再注意一下里面一层，也是一样，顺时针方向递增的一个环（比如n为4时，13, 14, 15, 16就是里面一层环）。以此类推，环里面还有一层环（n为4时有2层环，n为5时有3层环，最里面一层只有一个元素25），实际上是一个圆环套圆环结构。每一圆环最关键的元素就是左上角的那一个元素。只要知道了这个元素，再加上这个正方形环的边长就可以计算出剩下的元素。设左上角元素为a，边长为l（ell），也就是边上有几个元素，并假设左上角的行号和列号均为0，其它元素的行号和列号都以它作参考，计算方法如下所示：</p>
<p>1、若i == 0，<em>element</em>(<em>i, j</em>) = a + j;</p>
<p>2、否则若j == 0，<em>element</em>(<em>i, j</em>) = a + 4(l-4) - (i-1) - 1;</p>
<p>3、否则若i == l-1，<em>element</em>(<em>i, j</em>) = a + 4(l-4) - (l-2) - 1 - j;</p>
<p>4、否则<em>element</em>(<em>i, j</em>) = a + l - 1 + i;</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">int</span> a[<span class="number">10</span>][<span class="number">10</span>];</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">Fun</span><span class="params">(<span class="keyword">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">int</span> m=<span class="number">1</span>;</span><br><span class="line">	<span class="keyword">int</span> i,j;</span><br><span class="line">	<span class="keyword">for</span>(i =<span class="number">0</span>;i&lt;n/<span class="number">2</span>;i++)&#123;</span><br><span class="line">		<span class="keyword">for</span>(j=<span class="number">0</span>;j&lt;n-i;j++)&#123;</span><br><span class="line">			<span class="keyword">if</span>(a[i][j] ==<span class="number">0</span>)</span><br><span class="line">				a[i][j] = m++;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">for</span>(j=i+<span class="number">1</span>;j&lt;n-i;j++)&#123;</span><br><span class="line">			<span class="keyword">if</span>(a[j][n<span class="number">-1</span>-i] ==<span class="number">0</span>)</span><br><span class="line">				a[j][n<span class="number">-1</span>-i] = m++;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">for</span>(j=n-i<span class="number">-1</span>;j&gt;i;j--)&#123;</span><br><span class="line">			<span class="keyword">if</span>(a[n-i<span class="number">-1</span>][j] ==<span class="number">0</span>)</span><br><span class="line">				a[n-i<span class="number">-1</span>][j] = m++;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">for</span>(j=n-i<span class="number">-1</span>;j&gt;i;j--)&#123;</span><br><span class="line">			<span class="keyword">if</span>(a[j][i] ==<span class="number">0</span>)</span><br><span class="line">				a[j][i] = m++;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">if</span>(n%<span class="number">2</span>==<span class="number">1</span>)</span><br><span class="line">		a[n/<span class="number">2</span>][n/<span class="number">2</span>]=m;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">int</span> n,i;</span><br><span class="line">	<span class="built_in">cout</span>&lt;&lt;<span class="string">"请输入螺旋矩阵维数： "</span>&lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">	<span class="built_in">cin</span>&gt;&gt;n;</span><br><span class="line">	<span class="built_in">cout</span>&lt;&lt;<span class="string">"显示螺旋矩阵数值： "</span>&lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">	<span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;n;i++)&#123;</span><br><span class="line">		<span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j&lt;n;j++)&#123;</span><br><span class="line">			a[i][j]=<span class="number">0</span>;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	Fun(n);</span><br><span class="line">	<span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;n;i++)&#123;</span><br><span class="line">		<span class="keyword">for</span>( <span class="keyword">int</span> j=<span class="number">0</span>;j&lt;n;j++)&#123;</span><br><span class="line">			<span class="built_in">cout</span>&lt;&lt;a[i][j]&lt;&lt; <span class="string">"\t"</span>;</span><br><span class="line">		&#125;</span><br><span class="line">	<span class="built_in">cout</span>&lt;&lt;<span class="built_in">endl</span>;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="螺旋队列"><a href="#螺旋队列" class="headerlink" title="螺旋队列"></a>螺旋队列</h4><p>问题描述： 设1的坐标是（0，0），x方向向右为正，y方向向下为正，例如，7的坐标为（-1，-1），2的坐标为（1，0）。编程实现输入任意一点坐标（x，y），输出所对应的数字.</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"stdafx.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> max(a,b) ((a)&lt;(b)?(b):(a))</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> abs(a) ((a)&gt;0?(a):-(a))</span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">foo</span><span class="params">(<span class="keyword">int</span> x,<span class="keyword">int</span> y)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">int</span> t = <span class="built_in">max</span>(<span class="built_in">abs</span>(x),<span class="built_in">abs</span>(y));</span><br><span class="line">	<span class="keyword">int</span> u = t+t;</span><br><span class="line">	<span class="keyword">int</span> v = u<span class="number">-1</span>;</span><br><span class="line">	v= v*v+u;</span><br><span class="line">	<span class="keyword">if</span>(x == -t)</span><br><span class="line">		v+=u+t-y;</span><br><span class="line">	<span class="keyword">else</span> <span class="keyword">if</span>(y==-t)</span><br><span class="line">		v+=<span class="number">3</span>*u+x-t;</span><br><span class="line">	<span class="keyword">else</span> <span class="keyword">if</span>(y ==t)</span><br><span class="line">		v+= t-x;</span><br><span class="line">	<span class="keyword">else</span></span><br><span class="line">		v+=y-t;</span><br><span class="line">	<span class="keyword">return</span> v;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">int</span> _tmain(<span class="keyword">int</span> argc, _TCHAR* argv[])</span><br><span class="line">&#123;</span><br><span class="line">	<span class="keyword">int</span> x ,y;</span><br><span class="line">	<span class="keyword">int</span> N;</span><br><span class="line">	<span class="built_in">cout</span>&lt;&lt;<span class="string">"请输入螺旋队列数字： "</span>&lt;&lt;<span class="built_in">endl</span>;</span><br><span class="line">	<span class="built_in">cin</span>&gt;&gt;N;</span><br><span class="line">	<span class="built_in">cout</span>&lt;&lt;<span class="string">"显示螺旋队列数值： "</span>&lt;&lt;<span class="built_in">endl</span>;</span><br><span class="line">	<span class="keyword">for</span>(y=-N;y&lt;=N;y++)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">for</span>(x=-N;x&lt;=N;x++)</span><br><span class="line">			<span class="built_in">cout</span>&lt;&lt;<span class="string">"\t"</span>&lt;&lt;foo(x,y);</span><br><span class="line">		<span class="built_in">cout</span>&lt;&lt;<span class="built_in">endl</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">while</span>(<span class="built_in">scanf</span>(<span class="string">"%d%d"</span>,&amp;x,&amp;y)==<span class="number">2</span>)</span><br><span class="line">		<span class="comment">//printf("%d\n",foo(x,y));</span></span><br><span class="line">	    <span class="built_in">cout</span>&lt;&lt;<span class="string">"\t"</span>&lt;&lt;foo(x,y);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="双螺旋矩阵"><a href="#双螺旋矩阵" class="headerlink" title="双螺旋矩阵"></a>双螺旋矩阵</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> matrix[<span class="number">100</span>][<span class="number">100</span>];</span><br><span class="line">    <span class="keyword">int</span> m;</span><br><span class="line">    <span class="keyword">int</span> i;</span><br><span class="line">    <span class="keyword">int</span> j;</span><br><span class="line">    <span class="keyword">int</span> n;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &amp;m, &amp;n);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; m; i++)&#123;</span><br><span class="line">        <span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; n; j++)&#123;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &amp;matrix[i][j]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">int</span> rowBegin = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> rowEnd = m - <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">int</span> colBegin = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> colEnd = n - <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span> (rowBegin &lt;= rowEnd &amp;&amp; colBegin &lt;= colEnd)&#123;</span><br><span class="line">        <span class="comment">//先向右走</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = colBegin; i &lt;= colEnd; i++)&#123;</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%d"</span>, matrix[rowBegin][i]);</span><br><span class="line">            <span class="keyword">if</span> (rowBegin == rowEnd &amp;&amp; i == colEnd);</span><br><span class="line">            <span class="keyword">else</span> <span class="built_in">printf</span>(<span class="string">" "</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        rowBegin++;</span><br><span class="line">        <span class="comment">//向下走</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = rowBegin; i &lt;= rowEnd; i++)&#123;</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%d"</span>, matrix[i][colEnd]);</span><br><span class="line">            <span class="keyword">if</span> (colBegin == colEnd &amp;&amp; i == rowEnd);</span><br><span class="line">            <span class="keyword">else</span> <span class="built_in">printf</span>(<span class="string">" "</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        colEnd--;</span><br><span class="line">        <span class="comment">//向左走前先判定条件</span></span><br><span class="line">        <span class="keyword">if</span> (rowBegin &lt;= rowEnd)&#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = colEnd; i &gt;= colBegin; i--)&#123;</span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">"%d"</span>, matrix[rowEnd][i]);</span><br><span class="line">            <span class="keyword">if</span> (rowBegin == rowEnd &amp;&amp; i == colBegin);</span><br><span class="line">            <span class="keyword">else</span> <span class="built_in">printf</span>(<span class="string">" "</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            rowEnd--;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (colBegin &lt;= colEnd)&#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = rowEnd; i &gt;= rowBegin; i--)&#123;</span><br><span class="line">                <span class="built_in">printf</span>(<span class="string">"%d"</span>, matrix[i][colBegin]);</span><br><span class="line">            <span class="keyword">if</span> (colBegin == colEnd &amp;&amp; i == rowBegin);</span><br><span class="line">            <span class="keyword">else</span> <span class="built_in">printf</span>(<span class="string">" "</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            colBegin++;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="三、深入探究语言逻辑"><a href="#三、深入探究语言逻辑" class="headerlink" title="三、深入探究语言逻辑"></a>三、深入探究语言逻辑</h2><h3 id="动态分配内存"><a href="#动态分配内存" class="headerlink" title="动态分配内存"></a>动态分配内存</h3><p>1、栈区：C语言程序在编译时会被分配到内存上一篇有限的连续区域，这部分内存会被用于存储局部变量的值，这部分内存区域被称为栈区；</p>
<p>2、堆区：这部分内存是我们通过程序手动地向系统申请的，栈区内存带下编译时就已经被限制，如果使用超过限制的内存就会出现“溢出”的情况，而堆区的内存可以被一直申请使用，直至操作系统的有效内存无法再被申请位置；堆区被申请后，在使用的过程中若不释放就可能会出现内存泄漏；需要使用free(arr)；</p>
<p>3、全局区（静态区）：程序中的全局变量和静态变量都被存储在这块内存区域中；</p>
<p>如果需要使用堆上内存，需要将malloc.h，stdlib.h引入到程序中来。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> *p;</span><br><span class="line">p = (<span class="keyword">int</span> *) <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(<span class="keyword">int</span>));</span><br></pre></td></tr></table></figure>

<p>声明一个整数型的指针并向系统申请堆区上sizeof(int)的一块内存空间，并将指针p赋值为这片空间所在的起始地址；</p>
<p>malloc函数的返回值类型为void* ，这是一种特殊的指针类型，任何一个其他指针变量都可以直接被赋值给void*类型的指针，但如果反过来将无类型指针付给一个其他类型的指针变量，则必须要在前面加上被赋值指针变量的类型，如：(int *)，进行强制类型转换</p>

      
    </div>
    
    
    
    
    <div>
      
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/page/8/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/8/">8</a><span class="page-number current">9</span><a class="page-number" href="/page/10/">10</a><a class="extend next" rel="next" href="/page/10/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Li Yudong"
      src="/images/author.jpg">
  <p class="site-author-name" itemprop="name">Li Yudong</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">95</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">14</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">18</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/tiarmor1" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;tiarmor1" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:1157019137@qq.com" title="E-Mail → mailto:1157019137@qq.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2020 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Li Yudong</span>
</div>

        








      </div>
    </footer>
  </div>

  
  
  <script color='0,0,0' opacity='0.5' zIndex='-1' count='150' src="/lib1/canvas-nest/canvas-nest.min.js"></script>
  <script src="/lib1/anime.min.js"></script>
  <script src="/lib1/velocity/velocity.min.js"></script>
  <script src="/lib1/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  

  
   <canvas class="fireworks" style="position: fixed;left: 0;top: 0;z-index: 1; pointer-events: none;" ></canvas> 
   <script type="text/javascript" src="//cdn.bootcss.com/animejs/2.2.0/anime.min.js"></script> 
   <script type="text/javascript" src="/js/fireworks.js"></script>
  
</body>
</html>

